diff options
416 files changed, 12639 insertions, 6932 deletions
@@ -1,3 +1,1895 @@ +commit dbcb68f684a96d13efeb9993685f61b27b45e7dc +Author: Bdale Garbee <bdale@gag.com> +Date:   Sat Aug 12 00:21:43 2017 -0400 + +    update docinfo file for 1.8 release + +commit dfb9568866ba250a02039cc3429d5ca0603a60d9 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat Aug 12 00:10:23 2017 -0400 + +    Note that telebt 4.0 files need to go to altusmetrumllc dir +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 6b083e90d5b8de215f2f303f18b5c4ac9185622d +Author: Keith Packard <keithp@keithp.com> +Date:   Sat Aug 12 00:06:48 2017 -0400 + +    Bump version to 1.8 +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 243c1e519d41b45765d4edf5f608655d6ab01eff +Author: Keith Packard <keithp@keithp.com> +Date:   Sat Aug 12 00:06:26 2017 -0400 + +    doc: Add 1.8 release notes +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 7b67dcdd90317845261e51a1adb2404dcb0f2507 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat Aug 12 00:05:50 2017 -0400 + +    altosui, telegps: Add TeleBT v4.0 firmware to app packages +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 5fdce5b4a70ae59f8ac1ca10d9fadbbbd62412f3 +Merge: f1bbf1bd 2a3db289 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Aug 11 23:45:25 2017 -0400 + +    Merge remote-tracking branch 'origin/master' + +commit f1bbf1bd18d52a084af714a022b12bfc3c76374c +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Aug 11 23:40:41 2017 -0400 + +    ao-bringup: Allow dfu_util to "fail" while flashing chaoskey +     +    Sometimes it isn't happy about the exit status, but if the device +    comes up and works OK, we don't care. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit fbe87bd18308cab62eda6d5e956a8618095ed33b +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Aug 11 23:39:13 2017 -0400 + +    altoslib: Set time in state for KML output correctly +     +    Use new computed state_time value. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c7b34e6691b632199bc7802c2e4dea4de992578e +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jul 23 16:49:26 2017 -0700 + +    libaltos: Test both bluetooth and USB APIs with cjnitest +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 52bbfa9cd46ca27a4de937e89d48246a4e94c8a6 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jul 23 16:47:40 2017 -0700 + +    altos/test: Fix AES key format in test code +     +    Use temp variable instead of stepping on the AES name. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 9eaf917707287af57c2dadfc82d6d415b0964329 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jul 23 16:46:24 2017 -0700 + +    altos/test: Fix printf format for int64 arithmetic test +     +    Use 'long long' and %lld for 64-bit values when printing. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 198a3d4d5f51de5c0f0413299582479cde4e177f +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jul 23 16:37:27 2017 -0700 + +    altosui: Rename AltosConfig -> AltosConfigFC +     +    Now the class name says that this configures the flight computer. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c7c2fc2d85414fefda0a7948a6c4e38f65140861 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jul 23 16:38:09 2017 -0700 + +    altosui: Adapt to flight stats time value changes +     +    There aren't state time values anymore as those don't work when you +    have multiple motors. Instead, 'boost_time' is when the rocket left +    the pad and 'landed_time' is when it touched down. Use these new +    values in the --summary output. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2a3db28953f5cd981c519a917cdcd9f48dcb08e9 +Author: Bdale Garbee <bdale@gag.com> +Date:   Fri Jul 21 17:49:21 2017 -0600 + +    add TeleBT v4.0 to the list of stuff we build + +commit 04560a7cd6a64e742954a2d0fbd7563e2c310402 +Author: Bdale Garbee <bdale@gag.com> +Date:   Fri Jul 21 17:46:55 2017 -0600 + +    ignore more build products in telebt-v4.0 tree + +commit c8dbcaf69cd538a31ab6e2b568237ae7c8656a9a +Merge: 0cbfa444 ea3b5815 +Author: Bdale Garbee <bdale@gag.com> +Date:   Fri Jul 21 17:44:03 2017 -0600 + +    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 0cbfa444a9f9159cb509bb47ca5590fc1d709f64 +Author: Bdale Garbee <bdale@gag.com> +Date:   Fri Jul 21 17:43:38 2017 -0600 + +    clean up telefireone name references + +commit 3a1512b605a81ebee23cc6b7980b709a54cb43c9 +Author: Bdale Garbee <bdale@gag.com> +Date:   Fri Jul 21 17:42:54 2017 -0600 + +    rename existing turnon_telebt script, create a new one for v4.0 + +commit ea3b5815b27005b2f4c3034715f656d28ea8534e +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Jul 21 16:16:55 2017 -0700 + +    libaltos: Add btle test program +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 545bdc1f8046b08e237307d97d0044ddae9095b8 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Jul 21 16:14:31 2017 -0700 + +    altos/test: Add EasyMini test mode +     +    Use baro-only mode, parse easymini logs. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2969f0af52dfbdea7593b208e510c7b17227064c +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Jul 21 16:09:55 2017 -0700 + +    altoslib: fix adjustment of landed time +     +    Push landed time out if we computed silliness. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 30b308ad0189b4aa9dd5cc7ee876b55fee355a56 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Jul 21 16:05:45 2017 -0700 + +    Set version to 1.7.1 for TeleBT firmware build +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit b923e25a8a49dda40e62070dd2df6ff9130d4b38 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 27 23:39:16 2017 -0700 + +    altos/telebt-v4.0: Use HW flow control to BT module +     +    Now that the stmf0 HW flow control works... +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e64438271e481ca9f9eeb0ce2b1f9eca071b7ad4 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 27 23:37:49 2017 -0700 + +    altos/stmf0: Initialize UART RTS/CTS before turning it on +     +    If you try this after the UART is running, it won't work. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 46ff12a88136d3c274610255a918870aff9328cd +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 27 23:36:05 2017 -0700 + +    altoslib: Deal with multiple motors in flight stats +     +    Combine boost/fast/coast sections when computing ascent stats. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 13abb6739ae9be5a8733724c5d9b3f714f32bea4 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 27 21:37:50 2017 -0700 + +    altoslib: Fix comments in AltosQuaternion and AltosRotation +     +    Especially the nested comment which borked the compile +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 5a174f4a2caae97b5038eb92ab85303e736b7c2e +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 27 21:33:36 2017 -0700 + +    altosdroid: cal_data is no longer public from AltosState +     +    Use cal_data() method instead. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 6dbb362b2d1df4d8c2d301e90624aceef8051ef5 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu Jun 22 10:10:06 2017 -0700 + +    altoslib: Clean up quaternion and rotation interfaces +     +    Export euler to quaternion (instead of half_euler). +    Provide angles to rotate rather than rates and time. +    Add comments to quaternion and rotation code. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit ea7e236e75452e27f3af6730a0542850851eb23d +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 20 11:19:40 2017 -0700 + +    altos/rn4678: Add BLE support +     +    This just means ignoring the BLE connect status message. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 0da4e201041a4420f273c2e0cda77eea78099518 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 20 11:18:41 2017 -0700 + +    altoslib: Make cal_data private in AltosDataListener +     +    This way we can create it as needed. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a61217f0a6d0ef48b6471f632c4600255867e831 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 13 10:58:57 2017 -0700 + +    altoslib,altosuilib: Bump library version numbers +     +    The API and ABI have changed a bit since 1.7 +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e2fe220efe2ba375ddd925747a630c30c17d3bef +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 13 10:50:37 2017 -0700 + +    altosuilib: Rename AltosGraphNew to AltosGraph +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 3f9b6d23e4e33a58c179f45ffd42211ab327d8c6 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 13 10:47:54 2017 -0700 + +    altosuilib: Rename AltosUIGraphNew to AltosUIGraph +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e4f1fa544f1cb21070c9d79c81ebae0fb71d77db +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 13 10:46:03 2017 -0700 + +    altoslib: Rename AltosEepromNew to AltosEeprom +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 0e586ab3604bb695c36ae86c95f533197522fc65 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 13 10:38:13 2017 -0700 + +    altoslib: Remove old AltosEeprom.java code +     +    No longer in use +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 672889659fb2c1a63f5ef199173719a606a9f343 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 13 10:35:39 2017 -0700 + +    altos/telebt-4.0: Add dependency on RN4678 header +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit cd8b22bef0a88ed6881036b4c6718a4e33c55d41 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Jun 13 10:34:03 2017 -0700 + +    altos: Add timeout to RN4678 status message code +     +    If we see the start of an RN4678 status message, but then output +    pauses, assume that this isn't the start of a status message and flush +    the pending data. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 172d6cec981b50d4d5ff0f3d3bbd4377d55f57c8 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Jun 12 21:47:05 2017 -0700 + +    altosuilib: Don't display pad, last location in flight stats without gps +     +    Check stats.have_gps before displaying pad and last known location values. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 5eb91267348b0992414521520eda5c3a65e23ea7 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Jun 12 21:46:11 2017 -0700 + +    altoslib: Set time for TeleMini v1.0 eeprom analysing +     +    Need to take the computed tick time and tell the listener what time +    that cooresponds to. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit ee221ddf00f631a5f9d5d93468bfc697a26e4cfe +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 23:13:07 2017 -0700 + +    altosui, telegps, altosdroid: say ground distance, not total range +     +    Ground distance is more useful in predicting recovery than total range. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit cb1e757d4d486d04af0219b3f36ad17ee8095110 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 23:10:49 2017 -0700 + +    altoslib: Initialize new imu/mag values. Remove stale imu/mag objects. +     +    AltosState no longer has imu and mag objects, instead it just holds +    the values now. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 247fa1c669f987830540e618bf263b08284118df +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:52:56 2017 -0700 + +    altosui: Display current altitude in monitor idle Pad tab +     +    This was attempting to use 'pad' values even though monitor idle +    doesn't have them. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 03ec3e4c2247b6520c728b34805ad500be547a25 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:50:57 2017 -0700 + +    altoslib: Remove unused 'ground_rotation' from AltosState +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 97b42b7cd676232f13354798726f3087fa7177d5 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:50:28 2017 -0700 + +    altoslib: Flush igniter fire command +     +    This makes the igniter fire without a multi-second delay. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 5c4e473ef5d13da9c2f356702cb8767b55aa2137 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:49:46 2017 -0700 + +    altoslib: Hook up idle monitoring data again +     +    The API for idle monitoring changed, but these modules hadn't been +    fixed. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 27131ec7abda875595c61be0b151b73eb28afab9 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:47:53 2017 -0700 + +    altoslib: Fix labels in AltosIMU to match source data +     +    IMU bits arrive with X/Y/Z labels and are converted to the correct +    axes as they leave this object. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 43f8470dc66392dae4770882bfc6ad25b1d75436 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:47:02 2017 -0700 + +    altoslib: Keep time series in AltosFlightSeries array sorted +     +    This makes using the graph way easier. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 3fa1eadb91eea001342d2d357d7aaf661e8a2a5d +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:46:01 2017 -0700 + +    altoslib: Handle EasyMini v2.0 ADC values +     +    Different from EasyMini v1.0 +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 9454756f54312381927cb9faf1c4a6f5d8271034 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:43:57 2017 -0700 + +    altos: Create separate log format for EasyMini v2.0 +     +    The ADC in the STM32F0 is different than the LPC, with a range of +    0-4095 instead of 0-32767. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit ffbacb4ba9fc52de18bc54eb0d4b9e4f015ad1a4 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:42:25 2017 -0700 + +    altoslib: Missing config values now AltosLib.MISSING, not zero or negative +     +    Also fix AltosConfigData.java +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 8da38e5217f366a7da24a8af4a5ca620fad35df3 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:39:53 2017 -0700 + +    altoslib: Adapt to Mag sensor value ordering changes +     +    The HMC5883 sensor data is ordered x, z, y. Relabel everything to +    match that to preserve compatibility with existing firmware. With the +    data correctly ordered, fix the labling of the axes along, across and +    through. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2a05849c3bf8c1617409237be48802dd6fc6255b +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:34:11 2017 -0700 + +    altos: HMC5883 output order is X Z Y +     +    Re-label everything to have the correct names. This doesn't actually +    change the code at all, so the eeprom and telemetry is all compatible. +     +    Matching changes on the host side will be required to actually process +    the data correctly, of course. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit fed48732828c85ae56106cd72c5aeaaad47c552f +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 22:31:17 2017 -0700 + +    altos: Update sensor data atomically +     +    Read data into a temp variable, block interrupts, then update the +    published value. +     +    The bug is easy to see with the HMC5883 which has to byte-swap the +    output of the chip, and hence can occasionally get caught with the +    wrong byte order data. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 171adbe7db8520f5ff52a5fe2c54fe165c6f91f8 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Jun 11 16:11:09 2017 -0700 + +    altoslib, altosuilib, altosui, telegps: Missing config values now MISSING +     +    Config values that didn't apply to the current product used to get set +    to -1, but now they're set to AltosLib.MISSING to be consistent with +    the rest of the code. Deal with this in the UI bits. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit af6ce9a142d001f3b9b83cf6527f4dc848e94d48 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu Jun 8 20:39:06 2017 -0700 + +    altoslib: Compute 'vertical acceleration' for eeprom files +     +    This uses the computed orientation to find the portion of the measured +    acceleration which is vertical and then shows that in the post-flight +    analysis graph. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 32de85691f2e4ed1430a259e05a514ad820b32d9 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu Jun 8 20:37:58 2017 -0700 + +    altoslib: Compute orientation from eeprom data files +     +    This was lost in the AltosFlightSeries transformation. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 4c5acb57d7ac1abec7bb4cda9dc88c2a19767a2d +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 16:53:43 2017 -0700 + +    altoslib,altosuilib: Remove stale source files +     +    These aren't built any longer +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit b3cd7590f35babc346ba245d32d6290f22b2a13f +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 16:53:03 2017 -0700 + +    altoslib: Check for valid pad alt before computing GPS height series +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 93ec97cbae5a16d971b9e757c167bef9a5a80629 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 16:52:28 2017 -0700 + +    altoslib: Add status back to AltosFlightSeries for CSV export +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 8ec59ee5a6dda114ff55a4af4669842eed5ef79a +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 16:15:17 2017 -0700 + +    altoslib: Don't record radio status values in flight series +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 4b07adb395f2949dc76275d87b8af10430badb4b +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 16:14:53 2017 -0700 + +    altoslib: When no boost tick is found, just use first tick in file +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 78b4bf77fca96bef2cce443ad4c9544ae83f0acc +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 15:52:17 2017 -0700 + +    altoslib: Reset transient AltosCalData values before processing data +     +    Values in cal_data which are used to hold intermediate results need to +    get reset back to their initial values before processing a series of +    flight data again. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit dcf533d5befffa4c9c872f3c3d21d11ffeb61307 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 15:51:56 2017 -0700 + +    altoslib: Don't record 'pad' state in FlightSeries +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 9748d267b80e42ca52f9221900bb58602759a8d2 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 15:28:29 2017 -0700 + +    altosuilib: Set graph title to include product/serial/flight info +     +    Better than "Flight" +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 9a92ccbd3e5ce640875b614ff14d549cccc2036c +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 15:27:45 2017 -0700 + +    altoslib: Only compute state stats for recorded states +     +    Missing states shouldn't get stats; they 'didn't happen'. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 4161d9e9e5b4cbd71ec6d982d26ea566a69726c3 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 15:26:51 2017 -0700 + +    altoslib: Clean up gps series logging +     +    Create each gps series only when data are avaiable. +    Compute gps height series shen series is finished. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 8d6376c673af4648d494c1be71ad40380667bd25 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 15:26:11 2017 -0700 + +    altoslib: AltosFlightSeries ignore missing accel/pressure +     +    missing accel often comes from invalid cal data; easier to check here. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 15e3f2dae15e41a8501e3e1d221536751af15f94 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 15:25:35 2017 -0700 + +    altoslib: Remove debug printfs +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 355bb4669da05d202054b8265695e9878fd612c2 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 15:21:53 2017 -0700 + +    altoslib: Ignore invalid accel cal values +     +    When both are the same, something is wrong. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit bd7dd6f5adbe25708ba0276444196964f66b3c4a +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 14:42:30 2017 -0700 + +    altoslib: Check for empty gps height series +     +    When the gps height series is present but empty, there won't be a max value. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 1b91ba98395a431385c9af5de77b2892fd6ccc43 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 14:41:42 2017 -0700 + +    altoslib: Use first pressure value if no ground pressure available +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e0f25bcb8c036330e80c1254ab67f0bf323a4a98 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 14:33:28 2017 -0700 + +    altoslib: Handle eeprom tick wrapping +     +    Need to deal with eeprom files with tick values that cross the 16-bit +    barrier. +    Use 'wide_tick' to order eeprom record. +    Remeber 'prev_tick' to order cal data time sequence. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c075227c3a3c7714fe6f9d48c14dafaf4fed8e5e +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 14:03:51 2017 -0700 + +    altosuilib: Display product/firmware version in stats table +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 18f1dd64fe4ad94cbe292fffdc25167ae68c6611 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 14:02:51 2017 -0700 + +    altoslib: Adjust boost/landed time in flight series for display +     +    Makes the presented values match those used in the stats computation. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2c2eb1a15e745bb67721a1e3d84fb2fc0ce64eb1 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 14:02:11 2017 -0700 + +    altoslib: Add constants for speed/accel filtering +     +    With an eye towards letting the user pick. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit da914cd72411af8c36af05b13c11b9093c8a378c +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 14:00:15 2017 -0700 + +    altoslib: Create data file open helper in AltosLib +     +    Use InputStream everywhere, instead of Reader. +    Create private string input stream as java one is deprecated. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 9e1295ff74d03f940fc68e6795bf30687162a440 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun May 28 13:58:05 2017 -0700 + +    altoslib: Extract a few more values from config to cal_data +     +    Make it possible to display model/version data in the flight stats table. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e4407afb514437ccd8db79ae29c6fa203140fa07 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 23:42:52 2017 -0700 + +    altoslib: Recover from a couple of API changes +     +    Nothing serious. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c0af53c03d7945f7400496216ee259d73fb04843 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 23:35:02 2017 -0700 + +    micropeak: Use altoslib/altosuilib flight analysis bits +     +    Remove custom graph and stats bits and share bits with altosui. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 9e17d3be199d14473d8a7f9b899c290518b879a6 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 23:34:18 2017 -0700 + +    altosuilib: Remove 'cal_data' param from AltosGraphNew constructor +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a1d76d5568f8386c52704d69507132de23ea591f +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 23:33:37 2017 -0700 + +    altosuilib: Make AltosFlightStatsTable neater +     +    Elide missing data, change titles when data are simpler +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c87ba4b243a9fd838a3c97cc6a95cceb450a6ba5 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 23:33:07 2017 -0700 + +    altoslib: Provide consistent cal_data from idle and replay readers +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c9e82a5929a836bc61b464507badef2df5e9d4d0 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 23:32:29 2017 -0700 + +    altoslib: Return AltosTimeValue from min/max funcs +     +    Allowing the user to have both value and time. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 7ce82ea72009f7c9ac09be08aec154aec606d3c9 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 23:31:48 2017 -0700 + +    altoslib: Publish boost_time and landed_time from AltosFlightStats +     +    Nice to be able to use these when displaying data. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 3516eeb77048736470de2cc2ca03985efd228d29 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 23:30:54 2017 -0700 + +    altoslib: Allow for other tick sizes +     +    Use 1/100 sec by default, but provide for MicroPeak which uses a +    different step. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 9329cb607e36843385e92b677f095c451d50297c +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 23:30:13 2017 -0700 + +    altoslib: Change how speed/accel are computed from pressure +     +    Filter *then* differentiate. This works way better that doing things +    in the other order. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 855a7d243a5a85728a7b23fdfe9485d4ecaf71cf +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 16:12:31 2017 -0700 + +    telegps: Get telegps application working again +     +    Many minor API tweaks +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit b6b5c64f93fa56bcb22ea1c4279e4f754e6e6f1c +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 27 00:27:04 2017 -0700 + +    altosdroid: Deal with AltosState changes +     +    cal data split out from altos state. +    altos state needed to have no-arguments constructor for JSON code. +    Also messed with voice to make it stay quiet during app startup. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 8b4dcca73c65e87462d5f8d08dbc025aa8cf08a6 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 26 19:05:51 2017 -0700 + +    altoslib: Use cal data temp gps for telemetry data too +     +    This avoids bouncing the location data during flight +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 612756291c7fb68d337c3be2e8197d39e31f3b5c +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 26 18:47:18 2017 -0700 + +    altosui: Remove debug printf. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 0f32d1a2e2fb5989d124189a7eb1156a00b0ad8f +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 26 18:46:46 2017 -0700 + +    altoslib: Trim stale bits of AltosState +     +    Much of this is now in AltosCalData. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 21d864206043d2a6048cd859295623bad4d99365 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 26 18:46:00 2017 -0700 + +    altoslib: Preserve old GPS data during operation +     +    This avoids having the lat/lon values blank out when the GPS receiver +    looses lock. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 3d29882f5c70e627b0bbfe42c0a31d6cb5f6b6bf +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 26 18:22:02 2017 -0700 + +    altoslib: Get KML export working again +     +    Even annotate the states with avg speed/accel for fun. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit fd738d47bbc46d36698350d5450abe1125d990a3 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 26 17:14:29 2017 -0700 + +    altoslib: Make sure AltosFlightSeries is filled in before use +     +    After all of the raw data is captured, the derived data needs to be +    computed by calling the 'finish' function. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit af3c7938f24dcf5ffbce024ed596655b26282cf1 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 26 17:13:43 2017 -0700 + +    altosui: Remove --cat mode +     +    Wasn't documented, didn't do much useful. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit aa0300f11fe5b7f1d3e548e29dc809b803aa1f7a +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 26 00:51:37 2017 -0700 + +    altoslib: Make AltosReplayReader start synchronously enough to track states +     +    The Altos UI needs to see 'pad' state and then 'boost' state so that +    it will automatically switch tabs during the flight. When reading from +    eeprom files, the only way that is going to happen is if the reader +    thread waits until the UI has definitely seen 'pad' state, which we do +    by simply delaying the reader thread until after that has happened. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2e82051a6aaaccf1e8a242f9c8141e4167e652d2 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 26 00:20:17 2017 -0700 + +    altoslib,altosuilib,altosui: Get stats and replay working again. +     +    Stats are really easy with all of the data in memory. +    Replay takes a special thread to run the data and dump it into a +    single state. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 222158581887b5f9e8b9843d14321c313fa023fa +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 25 22:36:05 2017 -0700 + +    altoslib/altosuilib/altosui: More work towards using AltosFlightSeries for analysis +     +    Graphing and CSV seem complete now; stats still missing lots of stuff. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 4d497c1be534e2b206edec3c096198c8ea64cebe +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 25 17:29:31 2017 -0700 + +    altosui: Adapt to AltosFlightSeries for data analysis +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e6eb659b0e984515a33b3ddabfe8325742a952da +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 25 17:26:49 2017 -0700 + +    altosuilib: Adapt to AltosFlightSeries data processing plan +     +    Replace use of list of AltosState with AltosFlightSeries to improve +    data analysis. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit f26cfe417c6977cf1e7e75a4f050e25f64d41859 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 25 17:24:14 2017 -0700 + +    altoslib: Do data analysis on raw values rather than AltosState +     +    Use AltosFlightSeries instead of a sequence of AltosState records when +    processing saved data. This provides a better way of doing filtering +    and plotting. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 7600116a191b3ac252a0f716d200d0e0b3500987 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 23 14:53:55 2017 -0700 + +    altoslib: Don't store computed telemetry fields +     +    These values are only needed once, so there's no reason to save them. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit abcedc4b49ce77607ef95abf69479dc1d2c1b76d +Author: Keith Packard <keithp@keithp.com> +Date:   Mon May 22 14:36:46 2017 -0700 + +    doc: Add telegps outline +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e8794ab1d512418e312a1a779777119e20dc8c38 +Author: Bdale Garbee <bdale@gag.com> +Date:   Fri May 12 12:58:18 2017 -0600 + +    add thrust as a graphable time series type + +commit bbe0c2e0a3216f40f49af34b756330ba28d7c7e1 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 12 00:01:14 2017 -0700 + +    altosui: Hacks to plug into the new graph stuff +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 96de483d745ea0ef95326de2847a2534f7057846 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 11 17:16:56 2017 -0700 + +    altosuilib: Start creating new graph interface that takes time series data +     +    Replace the AltosState interface so the graph can get better data, and +    can be used for more stuff. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 258808d296aeadaf150fa9b07e9c99a6bf1ca7c8 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 11 17:14:51 2017 -0700 + +    altoslib: Create new abstraction underneath AltosState for recording values +     +    Provides a way for the graph API to see raw data values, instead of +    those cooked by AltosState. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a9aa2d3558c77eb444223eaa747c75916bc7bac1 +Author: Bdale Garbee <bdale@gag.com> +Date:   Thu May 11 12:14:41 2017 -0600 + +    altoslib: include TimeSeries code in build + +commit 81eaca2eac0b51a0017379187e042729b87e5f4d +Author: Keith Packard <keithp@keithp.com> +Date:   Wed May 10 15:18:13 2017 -0700 + +    altosuilib: Add time series subclass with data for generating a plot +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a50c8b40319c5d176d40a816111edd9a8dd48bc9 +Author: Keith Packard <keithp@keithp.com> +Date:   Wed May 10 15:16:34 2017 -0700 + +    altoslib: Add initial time series functions +     +    Provides the basis for offering a sequence of time/value datasets for +    graphing instead of using AltosState. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e37f9719745b7fba5bfb1b1517ce7b70efa7a3a2 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 19 21:36:01 2017 -0700 + +    altos/telebt-v3.0: Add send_packet command +     +    Useful for doing host-based RF protocols. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 6e3b7206f9ab2f76089553d7c881a96e0204a4a3 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 19 21:35:05 2017 -0700 + +    altos/telebt-v4.0: Remove HAS_POLLCHAR +     +    This isn't being used anymore. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit cbec54fc682774f096dc2e43ef9a4796be123341 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 19 21:31:52 2017 -0700 + +    ao-bringup: turnon_chaoskey: search for ao-usbload in PATH +     +    Don't assume it's in /usr/bin +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2cf4d76745713051c6ee9cf8d4b386c25f822433 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 19 21:30:29 2017 -0700 + +    altos/telefireone-v1.0: Fix confusing defines about config storage +     +    USE_INTERNAL_FLASH is about storing config data in internal flash, and +    should be on for telefireone. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 65fd7b23b1a8861afd74e4e42ce1918c059fbff1 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon May 15 12:13:35 2017 -0700 + +    altoslib: Set default accel cal for old TeleMetrum v1 files +     +    Before we stashed the config data in the log file, altoslib had to +    "known" what the accelerometer calibration values should be set +    to. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2fd949bb29d94b1a762ff707c98a8498ea508bb2 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon May 15 12:12:57 2017 -0700 + +    altoslib: Set default log format to FULL until we learn different +     +    Ancient log files don't even have a product name in them, so we'll +    guess TeleMetrum v1. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 404ee357d59ef4732068ec0e56a9c93ac885ea0f +Author: Keith Packard <keithp@keithp.com> +Date:   Mon May 15 12:11:31 2017 -0700 + +    altoslib: Mark AltosConfigData fields as MISSING until set +     +    Instead of using -1 or 0 randomly, use MISSING consistently. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit d0053c5e2cc7b75b642ff4727a1ef874d323db9d +Author: Bdale Garbee <bdale@gag.com> +Date:   Mon May 15 10:16:33 2017 -0600 + +    re-brand current telefiretwo product as telefireone + +commit ab50a1467bac0234062bc8c0a17783f1730aa981 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon May 15 08:59:52 2017 -0700 + +    altos/ao_rn4678: Send '$$$' for new devices. Fix name setting code. +     +    New devices won't respond to the cmd pin we have configured, so get +    them to command mode by sending the $$$ string. Somehow I'd botched +    the name setting code and hadn't caught it as I hadn't tried a new +    device... +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit f132a22995235f3002e4a2bb8771c9b5738efb30 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon May 15 08:58:21 2017 -0700 + +    altos/stmf: Fix up serial port flow control configuration bits +     +    Compute whether any sw/hw flow control is in use. +    Compute whether hw flow control is in use as a separate value. +     +    These make the code a bit easier to follow. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2536640b852feff41975d2da50befdda91ee6303 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 13 15:24:20 2017 -0700 + +    libaltos: Add support for TeleBT-v4.0 bluetooth channel change +     +    The RN4678 in TeleBT v4.0 uses channel 6 instead of channel 1. +    There is code in the linux bits which discovers this value, but that +    crashes when run under java for unknown reasons. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 91c2af9ac1387842a5fdc61dbc9e26e04de2cdd0 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 13 15:21:40 2017 -0700 + +    altoslib: Handle TeleBT v4.0 battery voltage +     +    The device reports raw ADC values, which mean AltosLib needs to +    translate them. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 7e0857120b8633c22603a9f59c5519e5a92759e9 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 13 15:19:25 2017 -0700 + +    altos/telebt-v4.0: Hook up RN4678 module +     +    We've switched from the BM70 to this module which offers a virtual +    serial channel over both BT and BTLE. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 6442e2ad6af4b337348aa2ce25abc91c05765826 +Author: Keith Packard <keithp@keithp.com> +Date:   Sat May 13 15:17:41 2017 -0700 + +    altos: Add RN4678 Bluetooth module driver +     +    This works much like the old BTM module, but supports both bluetooth +    and bluetooth LE. I've poked at it briefly over BTLE to see that it +    appears to have the right name, but haven't attempted to communicate +    over BTLE yet. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 9c6727d39cc1feae3bd0504bcbc910ae832e3651 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri May 12 01:35:52 2017 -0700 + +    Use SDP to locate the service channel on Linux +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 5ad767dd6b6c8d99bbe4b688e8cdbc230e01a7dc +Author: Keith Packard <keithp@keithp.com> +Date:   Wed May 10 14:47:15 2017 -0700 + +    altoslib: Another bit of altoslib for the old eeprom stuff +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 0080e61e5f2e20ce45041e29dc039d042aa7f76e +Author: Bdale Garbee <bdale@gag.com> +Date:   Thu May 11 11:27:30 2017 -0600 + +    have AltosGraph use new AltosPressure to get imperial_units working + +commit 9d05af2147c0eb6dc63c4d4dc1d9a3c31f480aef +Author: Bdale Garbee <bdale@gag.com> +Date:   Thu Apr 27 15:27:49 2017 -0600 + +    initial tests made using Terry's stand with a 2500psi sensor + +commit f753ad3b9d0f3dc9794e5dd097063aab6cf9bdc4 +Author: Bdale Garbee <bdale@gag.com> +Date:   Thu Apr 27 12:57:49 2017 -0600 + +    telefiretwo: don't try to record pre-burn sensor values in FLIGHT record + +commit 7e2b92ccb56b713fd18af5769156331ead8dc7ed +Author: Bdale Garbee <bdale@gag.com> +Date:   Thu Apr 27 15:21:53 2017 -0600 + +    have git ignore ao-bringup/cal_values + +commit 238e56e0f6ab2f623e0faf25298b38dc3a4aff74 +Author: Bdale Garbee <bdale@gag.com> +Date:   Wed May 10 22:19:38 2017 -0600 + +    telegps: use new eeprom reading code + +commit 0641326842bffbf4b3ae69459ca540131cb64e59 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 02:31:04 2017 -0700 + +    altoslib: Remove older eeprom handling code +     +    The new code appears to work in minor testing; time to try it all the time. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 17e20a6d2dab1f4bd1375bfd9e1c5230ee2c1119 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 02:11:25 2017 -0700 + +    altoslib: Save eeprom data in new .eeprom format +     +    A chunk of json for the config values followed by hex numbers for the data. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e311cefae19d7dc71fb10e9a943daa8e2313c8f8 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 00:22:35 2017 -0700 + +    altosui: Use new eeprom reading code +     +    This just means using different file opening functions, which then +    get matched by AltosEepromFile and sent off to the new eeprom code. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c00a80f040de85be18c9d5150cb0661e08158c3d +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 00:20:23 2017 -0700 + +    altoslib: Hack up AltosEepromFile to support new eeprom code +     +    Redirect when asked to read an eeprom file using the "Reader" type. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e14b0ea82420e769cdf9ffd621b7f8d4944ef44d +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 00:19:51 2017 -0700 + +    altoslib: Compile AltosForce and AltosPressure +     +    Useful if you want to actually use these. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e67a5c6ffa7174d66e985483fab4bf52ccaea5ca +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 00:19:05 2017 -0700 + +    altoslib: Add new eeprom management code +     +    Generic .eeprom file parsing, simpler per-type eeprom data extraction. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 44c0cecabb3a815dbf7f52e6b2dad364cc72b60c +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 00:17:40 2017 -0700 + +    altoslib: Add set_config_data to AltosState +     +    Initialize all config-data related state values. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit d3c1ce741c54c5640b7e1b07d86be1ce0951944b +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 00:17:11 2017 -0700 + +    altoslib: Add empty constructor for AltosPyro for JSON +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c17b78e60c340c8a3e3d6f9b875667c66216647a +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 00:16:36 2017 -0700 + +    altoslib: Add Ms5607 constructor that just takes config_data +     +    Use for making Ms5607 from eeprom files. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit d97c4d2f6de2981c2efd7bfbc9f5f9649987b854 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 00:14:33 2017 -0700 + +    altoslib: Add AltosForce and AltosPressure units +     +    Useful for TeleFireTwo. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 975751b604784e86b2ddb944a72b55ca3f14cf63 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 9 00:13:16 2017 -0700 + +    altoslib: Hide members from json by prefixing with __ +     +    This lets some structures which would otherwise recurse (and crash) +    get converted to json, assuming the hidden members aren't relevant. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 08da6f2100c0241c70554427e53b7e237dfda16c +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 4 22:09:31 2017 -0700 + +    altos/telemini-v3.0: Use dbg connector pin 5 for force bootloader +     +    This works way better than attempting to use the beeper pin. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 178d7c0aa32267ea71be2ccff146ea6ff990d7dc +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 4 22:07:51 2017 -0700 + +    altos/telemini-v3.0: Add 'recovery mode' on PA14 (pin 6 on dbg header) +     +    Connect this pin to GND (pin 3) and TeleMini will come up with N0CALL +    at 434.550MHz using the original frequency calibration. Helps recover +    from accidental mis-configuration. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 3b4e3189211801c6f8f41c5d08c5a8551f28976c +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 4 22:06:16 2017 -0700 + +    altos: Move 'ao_force_freq' to ao_config.c +     +    Instead of having to add it to each product using this variable. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e76d543a203f210683cb77df2b9bbff1a9f4b381 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu May 4 22:04:57 2017 -0700 + +    altos: Make CDC ACM 'line coding' public +     +    This allows other systems to see what baud rate the host has requested. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a84bc1bd8dd19d47709614b0c2639958d09fbf7e +Author: Miguel Benavidez <miguelbenavidez1145@gmail.com> +Date:   Thu May 4 11:29:33 2017 -0700 + +    altoslib: Fix MS5607 raw data to pressure conversion function +     +    The MS5607 sensor provides raw 24-bit ADC outputs to the host along +    with calibration constants necessary to convert those into temperature +    and pressure values. The datasheet has a flow chart indicating how to +    perform this computation. There are two parts of the algorithm which +    adjust the result based on the ambient temperature, temperatures below +    20°C get one compensation factor and temperatures below -15°C get an +    additional factor. +     +    The ground station version of this function mistakenly applied the +    second compensation factor for all temperatures below +15°C. The +    result was that the pressure computed on the ground when the measured +    temperature was between -15°C and +15°C was incorrect, resulting in +    altitudes which were several hundred meters off in some situations. +     +    This can be seen when displaying any .eeprom (or .mpd) data +    files for flights with temperatures in that range. The datafiles +    themselves are not corrupted, only the display operation. +     +    This is not seen for telemetry data, where the pressure and associated +    altitude is computed in the airframe using the correct algorithm. +     +    Thanks much to Miguel and the rest of the Vanguard School TARC team +    for identifying the problem and providing this fix. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 643f7508233f492a86f541b4f4fb20531b306ae0 +Author: Bdale Garbee <bdale@gag.com> +Date:   Wed May 3 11:47:33 2017 -0600 + +    altos/telebt-v4.0 Set CPU clock to 48Mhz instead of 96Mhz + +commit a6e1010f7519c5d1243e8950df6f022576152a87 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 2 11:49:21 2017 -0700 + +    altos/telegps-v2.0: Disable external serial port to save ROM +     +    We'll have to rewrite some of the serial code to avoid sucking memory here. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 475940cb8032c76622c64dd0bd30f31c0b0f6cf4 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue May 2 11:35:18 2017 -0700 + +    altos/stmf0: Add code to use SoC flash as storage +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit de36a1e1a2e568dd606000f169fef111e8c08b15 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Apr 30 17:42:23 2017 -0700 + +    altos/telegps-v2.0: Reorder initialization sequence +     +    This tries to be a bit more logical about the board initialization +    sequence, starting with the OS, then the support hardware, internal +    drivers, external drivers and finally services. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 9a10a209749d1f375d02ce9af68ccbb0b3a91ba2 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Apr 30 17:41:21 2017 -0700 + +    altos/telegps-v2.0: CC1200 CS is PA1, not PA5. +     +    Also remove some unneeded config of an additional pin for MCU wakeup, +    which the CC1120 needs but the CC1200 does not. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 99c5c47d9288721a1fe009698393c67dd36a16fb +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Apr 30 17:40:26 2017 -0700 + +    altos/telegps-v2.0: GPS chip is connected to serial 2, not serial 1 +     +    Turn on serial 2 and use it for GPS. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 7ace97885c4924de049ff20a40fd9ec234b6577b +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Apr 30 17:39:54 2017 -0700 + +    altos/telegps-v2.0: Remove some unneeded defines +     +    HAS_MS5607 and HAS_RADIO_RECV aren't useful. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 0f883aa1b1a1db61113489c260f44c09d5216bc7 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Apr 30 17:39:03 2017 -0700 + +    altos/telegps-v2.0: Battery ADC input is on PB1, not PA0 +     +    Rewire as needed. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 979a1b8d80189e56745316da3de9288ee32e102c +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Apr 30 17:38:21 2017 -0700 + +    altos/telegps-v2.0: Set CPU clock to 48MHz instread of 96MHz +     +    Turns out the CPU doesn't run well at that speed. Who would have guessed? +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 671e00f9fa75d75b5f15d8cc558a46a9651690fa +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Apr 30 17:37:45 2017 -0700 + +    altos/telegps-v2.0: Adjust LED config +     +    The LED is green, not red. Use it for panic and GPS lock. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit ec963d358895ae46af63d2a6e9a32bdfb4d631c0 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Apr 30 17:35:28 2017 -0700 + +    altos/kernel: Allow TeleGPS v2 to scale battery in telem +     +    TeleGPS v2 uses the STMF0 processor instead of the LPC11, which means +    the ADC range is different. As the raw ADC value was getting sent to +    represent battery voltage in the config packet, we need to scale that +    for the different processor. This patch allows that to happen. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 34fda7bff76d59bcfbcec6a44275829c45e42189 +Author: Keith Packard <keithp@keithp.com> +Date:   Sun Apr 30 17:34:08 2017 -0700 + +    src/kernel: Add GPS lock blink LED to tracker code +     +    Blinks an LED briefly once every three seconds when GPS is locked. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c02adbdd8f41c1aa1fdf4748c910d23e5485108f +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Apr 28 00:08:51 2017 -0700 + +    altos: Build MicroPeak-v2.0 by default +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 217d77dadbef4192d2f32e290a5c5f50159f2e0d +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Apr 28 00:07:03 2017 -0700 + +    altos/micropeak-v2.0: Add initial MicroPeak v2 support +     +    stm32f042 processor replaces the attiny85 and adds USB support along +    with more storage. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 65bb93f69b2f420281b67d62a9ee3cf30874fb7c +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Apr 28 00:05:01 2017 -0700 + +    altos/stmf0: Add support for HSI clocked applications +     +    And allow application space to be limited to less than available flash. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit d197adf353ec5503c72a4554aca2a463bb685932 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Apr 28 00:04:33 2017 -0700 + +    altos/stmf0: Fix HSI clock rate. +     +    It's 8MHz, not 16MHz +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2b3c79e9d88c9bb0b5aca4bc20fa942ebcfe40fc +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Apr 28 00:04:14 2017 -0700 + +    altos/stmf0: Make sure systick is off before programming +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit ac3fc7da669f58c7abd25b0ca8cc425238b84217 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Apr 28 00:02:54 2017 -0700 + +    altos/stmf0: Compute serial baud rate registers at runtime +     +    This allows the system clock to vary at runtime, instead of requiring +    a fixed value. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 7d4f7880b0934c208df65cea8b0f549f32f1c7d2 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Apr 28 00:02:02 2017 -0700 + +    altos/micropeak: Update ao_micropeak.h for MicroPeak v2 +     +    Allow different sample times, add constant for MicroPeak v2 log files. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 4896582922ba5227da031c762221c8c7eafc2415 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Apr 28 00:01:18 2017 -0700 + +    altos/micropeak: Use existing ao_ms5607_current variable +     +    Instead of defining another. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 4d4675cbadcb0ab9df8f6d5155797dca400315c0 +Author: Keith Packard <keithp@keithp.com> +Date:   Fri Apr 28 00:00:11 2017 -0700 + +    altos: Add header file for ao_report_micro.c +     +    Defines the functions in this file. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 75c26a26e905e3d4f141badfcb6ec6995ed58213 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu Apr 27 23:59:27 2017 -0700 + +    altos: Add 100ms constants for baro Kalman filter +     +    MicroPeak v2 uses this rate. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 8c755f52db40bb845ab236ff400f35888053e616 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu Apr 27 23:52:29 2017 -0700 + +    altos: Adapt micro log to MicroPeak V3 +     +    Allow use of regular serial API for sending data. +    Allow application to specify different storage size. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2245d9e3178404a49a6787656319fa13f0cc1a51 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu Apr 27 23:51:21 2017 -0700 + +    altos/ms5607: Allow applications to not use the normal data ring and thread +     +    MicroPeak V2 has tasks, but doesn't want to use another thread just +    for the MS5607. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 6813f48fe02ecc5902f386234535ea76af71a764 +Author: Keith Packard <keithp@keithp.com> +Date:   Thu Apr 27 23:50:12 2017 -0700 + +    micropeak: Add MicroPeak V2 to the download code +     +    Add the MicroPeak V2 sample rate so the timing values are correct. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a59c3afa23e876362dc8c80559015ce361627f05 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Apr 25 23:56:41 2017 -0700 + +    Fake thrust data as accel for now + +commit 07956b102bd4b7e4dd0ec20e0a4fbe3779acfdd9 +Author: Keith Packard <keithp@keithp.com> +Date:   Tue Apr 25 21:27:40 2017 -0700 + +    ao-bringup: make turnon_telemini search for ao_usbload on $PATH +     +    I've uninstalled the altos package as it has a version of ao-usbload +    which is too old for telemini. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2b014fe9fa64e7aead586bc682251346d000c8cc +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 23:06:34 2017 -0600 + +    telemini-v3.0: make git ignore build products + +commit b662ca4edd67a2e1e5712f97fb1ce909f19af625 +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 23:01:53 2017 -0600 + +    ao-tools/ao-makebin: have git ignore built object + +commit bd489b96b060c8276bd7709ac55c306aad02374c +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 23:00:34 2017 -0600 + +    telebt-v4.0: make git ignore products of build + +commit 6ed63dfbf0a0205df17afb2ea54afad441a69604 +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 22:58:00 2017 -0600 + +    telegps-v2.0: slow down radio chip spi speed + +commit 08d73614c0c0859bc097c1d7d423bac4cf313512 +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 22:28:28 2017 -0600 + +    telebt-v4.0: slow down SPI speed to radio chip + +commit 16f171350619b9d3da614625e27c092b144c3097 +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 22:26:12 2017 -0600 + +    telebt-v4.0: turn off pin remapping in the flash loader, too + +commit 514c05c287f0be390cfdf3491169c830cad8bfe7 +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 22:12:42 2017 -0600 + +    telebt-v4.0: don't need the USB pin remapping flag + +commit 1f723d31312be6dea3ef46e265c17c4d361d7099 +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 22:10:41 2017 -0600 + +    telebt-v4.0: add ao_send_packet + +commit 30e6e087b639c6d7ec75f21ba8c6fcf6ad50fffe +Merge: b2a5118d 75881968 +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 22:04:22 2017 -0600 + +    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit b2a5118dededd1ed6b1326e82168214cb0b24821 +Author: Bdale Garbee <bdale@gag.com> +Date:   Tue Apr 25 22:03:56 2017 -0600 + +    telebt-v4.0: initial creation of firmware for new product, no BT yet + +commit 75881968ffb6bfd4e920cac4aa15d8d188eda119 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 17:06:01 2017 -0700 + +    altos/nucleo-32: Add lisp save/restore +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 97cf9df882291b9e494b2f64f84eb37357a6ab31 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 17:01:43 2017 -0700 + +    altos/telegps-v2.0: git ignore make results +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a324ce39bb7abadc70785a6fdce449c9441f87b2 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 17:00:10 2017 -0700 + +    Ignore ao_lisp_test + +commit 7064aa67189108c4ade3d2e7eac9a704b7849626 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 22:26:31 2017 -0700 + +    Update releasing to add more firmware bits +     +    Also, document what is needed to get a new product into the build +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit f0f69ab309869e914536d674d49d68a8dd31b080 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 22:25:57 2017 -0700 + +    altosui: Add TeleMini v3.0 and EasyMini v2.0 firmware to windows package +     +    Sigh. This can't easily be done from Makefile.am +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 8b9557f7946703888be97633cf3e54216c652f30 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 22:25:14 2017 -0700 + +    altos/ao-bringup: Switch turnon_easymini to v2.0 +     +    Not planning on buildin more v1.0 boards +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 0d685ac0916229c23a299b11dad48af749eb27ea +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 22:01:04 2017 -0700 + +    altosui: Ship telemini v3.0 firmware +     +    Even though we don't provide a cable for reflashing yet +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit d7d1452d03bcfb14990546d57d9d858ae3135008 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 21:59:16 2017 -0700 + +    altos: Add telemini-v3.0 and easymini-v2.0 to default altos build +     +    Make sure they get built for releases +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 41d5bb89973c7a358d08c538f1b52c45b0bbec30 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 21:56:14 2017 -0700 + +    altos/easymini-v2.0: Add EasyMini v2.0 +     +    Like EasyMini v1.0, but with the STM32F0 processor instead of LPC +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 43cf1991f042e50fb6ec0b037f6d212436e3d31b +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 21:54:25 2017 -0700 + +    altos/telemini-v3.0: Fix license +     +    Was GPL2, switch to GPL2+ +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit e0be779ac401f063b968aaac9460c972a728d309 +Author: Keith Packard <keithp@keithp.com> +Date:   Mon Apr 24 21:32:02 2017 -0700 + +    altos/stmf0: Not all timer configurations use AF2 +     +    Allow applications to select other configurations. +     +    Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 202d556241d56ec4a27f202575d6945dc09f9e03 +Author: Bdale Garbee <bdale@gag.com> +Date:   Mon Apr 24 20:04:37 2017 -0600 + +    add telemini-v3.0 to list of binaries we stach in LLC repo for production use + +commit ef7fbbfa308918ebae5d2499aabccc6562a80dfa +Author: Bdale Garbee <bdale@gag.com> +Date:   Mon Apr 24 19:46:05 2017 -0600 + +    two more places where telemini-outline.pdf filename needs to be updated +  commit 9c95bed92a45741e6c1ad0ab4941f13370b77648  Author: Keith Packard <keithp@keithp.com>  Date:   Mon Apr 24 15:47:08 2017 -0700 diff --git a/Makefile.am b/Makefile.am index 4145946e..2fdbd109 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,6 +53,7 @@ fat_altos = \  	src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx \  	src/telebt-v1.0/telebt-v1.0-$(VERSION).ihx \  	src/telebt-v3.0/telebt-v3.0-$(VERSION).ihx \ +	src/telebt-v4.0/telebt-v4.0-$(VERSION).ihx \  	src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx \  	src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx \  	src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx \ @@ -1,3 +1,12 @@ +Adding a product to the release + +	Make sure the firmware and loader get built by default in +	src/Makefile + +	Add the firmware to altosui/Makefile.am + +	Add the firmware to altosui/altos-windows.nsi.in +  These are Bdale's notes on how to do a release.  	- make sure build environment is up to date @@ -69,23 +78,31 @@ These are Bdale's notes on how to do a release.  		this pushes packages for each platform to web site  	# store a stable copy of ARM binaries for production use -	cp src/easymega-v1.0/*.elf \ -	   src/easymini-v1.0/*.elf \ -	   src/telebt-v3.0/*.elf \ -	   src/teledongle-v3.0/*.elf \ -	   src/telegps-v1.0/*.elf \ -	   src/telemega-v1.0/*.elf \ -	   src/telemega-v2.0/*.elf \ -	   src/telemetrum-v2.0/*.elf \ +	cp src/chaoskey-v1.0/{*.elf,*.ihx} \ +	   src/easymega-v1.0/{*.elf,*.ihx} \ +	   src/easymini-v1.0/{*.elf,*.ihx} \ +	   src/easymini-v2.0/{*.elf,*.ihx} \ +	   src/telebt-v3.0/{*.elf,*.ihx} \ +	   src/telebt-v4.0/{*.elf,*.ihx} \ +	   src/teledongle-v3.0/{*.elf,*.ihx} \ +	   src/telegps-v1.0/{*.elf,*.ihx} \ +	   src/telemega-v1.0/{*.elf,*.ihx} \ +	   src/telemega-v2.0/{*.elf,*.ihx} \ +	   src/telemetrum-v2.0/{*.elf,*.ihx} \ +	   src/telemini-v3.0/{*.elf,*.ihx} \  	   ~/altusmetrumllc/Binaries/ -	cp src/easymega-v1.0/flash-loader/*.elf \ +	cp src/chaoskey-v1.0/flash-loader/{*.elf,*.bin} \ +	   src/easymega-v1.0/flash-loader/*.elf \  	   src/easymini-v1.0/flash-loader/*.elf \ +	   src/easymini-v2.0/flash-loader/{*.elf,*.bin} \  	   src/telebt-v3.0/flash-loader/*.elf \ +	   src/telebt-v4.0/flash-loader/*.elf \  	   src/teledongle-v3.0/flash-loader/*.elf \  	   src/telegps-v1.0/flash-loader/*.elf \  	   src/telemega-v1.0/flash-loader/*.elf \  	   src/telemega-v2.0/flash-loader/*.elf \  	   src/telemetrum-v2.0/flash-loader/*.elf \ +	   src/telemini-v3.0/flash-loader/{*.elf,*.bin} \  	   ~/altusmetrumllc/Binaries/loaders/  	(cd ~/altusmetrumllc ; git add Binaries ; git commit -a)   	(cd ~/altusmetrumllc ; git push)  diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 8e65e1d0..359b5832 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -31,7 +31,7 @@ import android.bluetooth.BluetoothSocket;  import android.os.Handler;  //import android.os.Message; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosBluetooth extends AltosDroidLink { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java index b8c90773..5906ff98 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java @@ -21,7 +21,7 @@ import java.util.Arrays;  import java.io.*;  import java.lang.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import android.app.Activity;  import android.graphics.*; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 30a949d5..924ab4c9 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -52,7 +52,30 @@ import android.hardware.usb.*;  import android.graphics.*;  import android.graphics.drawable.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; + +class SavedState { +	long	received_time; +	int	state; +	boolean	locked; +	String	callsign; +	int	serial; +	int	flight; +	int	rssi; + +	SavedState(AltosState state) { +		received_time = state.received_time; +		this.state = state.state(); +		if (state.gps != null) +			locked = state.gps.locked; +		else +			locked = false; +		callsign = state.cal_data().callsign; +		serial = state.cal_data().serial; +		flight = state.cal_data().flight; +		rssi = state.rssi; +	} +}  public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener { @@ -114,6 +137,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  	public Location location = null; +	private AltosState	state; +	private SavedState	saved_state; +  	// Tabs  	TabHost         mTabHost;  	AltosViewPager  mViewPager; @@ -123,7 +149,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  	// Timer and Saved flight state for Age calculation  	private Timer timer; -	AltosState saved_state; +  	TelemetryState	telemetry_state;  	Integer[] 	serials; @@ -307,7 +333,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  		if (telemetry_state.states.containsKey(current_serial)) {  			state = telemetry_state.states.get(current_serial); -			int age = state_age(state); +			int age = state_age(state.received_time);  			if (age < 20)  				aged = false;  			if (current_serial == selected_serial) @@ -322,7 +348,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  			for (int serial : telemetry_state.states.keySet()) {  				AltosState	existing = telemetry_state.states.get(serial); -				int		existing_age = state_age(existing); +				int		existing_age = state_age(existing.received_time);  				if (newest_state == null || existing_age < newest_age) {  					newest_state = existing; @@ -334,7 +360,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  				state = newest_state;  		} -		update_ui(telemetry_state, state); +		update_ui(telemetry_state, state, telemetry_state.quiet);  		start_timer();  	} @@ -362,8 +388,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  			blend_component(a, b, r, 24, 0xff));  	} -	int state_age(AltosState state) { -		return (int) ((System.currentTimeMillis() - state.received_time + 500) / 1000); +	int state_age(long received_time) { +		return (int) ((System.currentTimeMillis() - received_time + 500) / 1000);  	}  	void set_screen_on(int age) { @@ -375,7 +401,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  	void update_age() {  		if (saved_state != null) { -			int age = state_age(saved_state); +			int age = state_age(saved_state.received_time);  			double age_scale = age / 100.0; @@ -399,17 +425,19 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  		}  	} -	void update_ui(TelemetryState telem_state, AltosState state) { +	void update_ui(TelemetryState telem_state, AltosState state, boolean quiet) { + +		this.state = state;  		int prev_state = AltosLib.ao_flight_invalid;  		AltosGreatCircle from_receiver = null;  		if (saved_state != null) -			prev_state = saved_state.state(); +			prev_state = saved_state.state;  		if (state != null) { -			set_screen_on(state_age(state)); +			set_screen_on(state_age(state.received_time));  			if (state.state() == AltosLib.ao_flight_stateless) {  				boolean	prev_locked = false; @@ -417,8 +445,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  				if(state.gps != null)  					locked = state.gps.locked; -				if (saved_state != null && saved_state.gps != null) -					prev_locked = saved_state.gps.locked; +				if (saved_state != null) +					prev_locked = saved_state.locked;  				if (prev_locked != locked) {  					String currentTab = mTabHost.getCurrentTabTag();  					if (locked) { @@ -456,22 +484,22 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  								     state.gps.alt);  			} -			if (saved_state == null || !same_string(saved_state.callsign, state.callsign)) { -				mCallsignView.setText(state.callsign); +			if (saved_state == null || !same_string(saved_state.callsign, state.cal_data().callsign)) { +				mCallsignView.setText(state.cal_data().callsign);  			} -			if (saved_state == null || state.serial != saved_state.serial) { -				if (state.serial == AltosLib.MISSING) +			if (saved_state == null || state.cal_data().serial != saved_state.serial) { +				if (state.cal_data().serial == AltosLib.MISSING)  					mSerialView.setText("");  				else -					mSerialView.setText(String.format("%d", state.serial)); +					mSerialView.setText(String.format("%d", state.cal_data().serial));  			} -			if (saved_state == null || state.flight != saved_state.flight) { -				if (state.flight == AltosLib.MISSING) +			if (saved_state == null || state.cal_data().flight != saved_state.flight) { +				if (state.cal_data().flight == AltosLib.MISSING)  					mFlightView.setText("");  				else -					mFlightView.setText(String.format("%d", state.flight)); +					mFlightView.setText(String.format("%d", state.cal_data().flight));  			} -			if (saved_state == null || state.state() != saved_state.state()) { +			if (saved_state == null || state.state() != saved_state.state) {  				if (state.state() == AltosLib.ao_flight_stateless) {  					mStateLayout.setVisibility(View.GONE);  				} else { @@ -485,15 +513,16 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  				else  					mRSSIView.setText(String.format("%d", state.rssi));  			} +			saved_state = new SavedState(state);  		}  		for (AltosDroidTab mTab : mTabs)  			mTab.update_ui(telem_state, state, from_receiver, location, mTab == mTabsAdapter.currentItem()); +		AltosDebug.debug("quiet %b\n", quiet);  		if (mAltosVoice != null) -			mAltosVoice.tell(telem_state, state, from_receiver, location, (AltosDroidTab) mTabsAdapter.currentItem()); +			mAltosVoice.tell(telem_state, state, from_receiver, location, (AltosDroidTab) mTabsAdapter.currentItem(), quiet); -		saved_state = state;  	}  	private void onTimerTick() { @@ -567,8 +596,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  		// Display the Version  		mVersion = (TextView) findViewById(R.id.version);  		mVersion.setText("Version: " + BuildInfo.version + -		                 "  Built: " + BuildInfo.builddate + " " + BuildInfo.buildtime + " " + BuildInfo.buildtz + -		                 "  (" + BuildInfo.branch + "-" + BuildInfo.commitnum + "-" + BuildInfo.commithash + ")"); +				 (AltosVersion.has_google_maps_api_key() ? " maps" : "") + +		                 " Built: " + BuildInfo.builddate + " " + BuildInfo.buildtime + " " + BuildInfo.buildtz + +		                 " (" + BuildInfo.branch + "-" + BuildInfo.commitnum + "-" + BuildInfo.commithash + ")");  		mCallsignView  = (TextView) findViewById(R.id.callsign_value);  		mRSSIView      = (TextView) findViewById(R.id.rssi_value); @@ -703,7 +733,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  					 location.getLatitude(),  					 location.getLongitude()); -		update_ui(telemetry_state, saved_state); +		update_ui(telemetry_state, state, true);  	}  	@Override @@ -1094,7 +1124,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,  		AltosDebug.debug("Location changed to %f,%f",  				 location.getLatitude(),  				 location.getLongitude()); -		update_ui(telemetry_state, saved_state); +		update_ui(telemetry_state, state, false);  	}  	public void onStatusChanged(String provider, int status, Bundle extras) { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java index 23105635..05cb0f6b 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java @@ -25,7 +25,7 @@ import java.util.UUID;  import android.os.Handler; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public abstract class AltosDroidLink extends AltosLink { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java index 2b78104d..8730e8ad 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java @@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid;  import java.util.*;  import java.io.*;  import android.location.Location; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public interface AltosDroidMapInterface {  	public void onCreateView(AltosDroid altos_droid); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java index c7cdc961..0670005a 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java @@ -22,7 +22,7 @@ import java.util.*;  import java.text.*;  import android.content.Context; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosDroidPreferences extends AltosPreferences { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java index 2e6ccb34..01ec0af9 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java @@ -25,7 +25,7 @@ import android.content.SharedPreferences;  import android.os.Environment;  import android.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {  	public final static String        NAME    = "org.altusmetrum.AltosDroid"; @@ -77,7 +77,17 @@ public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {  	}  	public String getString(String key, String def) { -		return prefs.getString(key, def); +		String	ret; +		ret = prefs.getString(key, def); +//		AltosDebug.debug("AltosDroidPreferencesBackend get string %s:\n", key); +//		if (ret == null) +//			AltosDebug.debug("      (null)\n"); +//		else { +//			String[] lines = ret.split("\n"); +//			for (String l : lines) +//				AltosDebug.debug("        %s\n", l); +//		} +		return ret;  	}  	public byte[] getBytes(String key, byte[] def) { @@ -103,6 +113,10 @@ public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {  	}  	public void putString(String key, String value) { +//		AltosDebug.debug("AltosDroidPreferencesBackend put string %s:\n", key); +//		String[] lines = value.split("\n"); +//		for (String l : lines) +//			AltosDebug.debug("        %s\n", l);  		editor.putString(key, value);  	} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java index 11d8f624..71309897 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java @@ -18,7 +18,7 @@  package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import android.location.Location;  import android.app.Activity;  import android.graphics.Color; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java index 76771adc..2a728cf7 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java @@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid;  import java.util.*;  import java.io.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import android.app.Activity;  import android.graphics.*; @@ -164,6 +164,7 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal  						break;  					case AltosMapTile.forbidden:  						message = "Too many requests, try later"; +						AltosDebug.debug("Forbidden map response %d\n", AltosMapStore.forbidden_response);  						break;  					}  					if (message != null) { @@ -476,11 +477,11 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal  				if (t_state.gps != null) {  					AltosLatLon	latlon = new AltosLatLon(t_state.gps.lat, t_state.gps.lon);  					rocket.set_position(latlon, t_state.received_time); -					if (state.serial == serial) +					if (state.cal_data().serial == serial)  						there = latlon;  				}  				if (state != null) -					rocket.set_active(state.serial == serial); +					rocket.set_active(state.cal_data().serial == serial);  			}  		}  		if (receiver != null) { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java index 9e5d6dee..b71cdd62 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java @@ -20,7 +20,7 @@ package org.altusmetrum.AltosDroid;  import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import com.google.android.gms.maps.*;  import com.google.android.gms.maps.model.*; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java index 8d0a725a..77947b4b 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java @@ -29,7 +29,7 @@ import android.hardware.usb.*;  import android.app.*;  import android.os.Handler; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosUsb extends AltosDroidLink { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java index 811b0367..fedfdb52 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java @@ -23,7 +23,7 @@ import android.speech.tts.TextToSpeech;  import android.speech.tts.TextToSpeech.OnInitListener;  import android.location.Location; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosVoice { @@ -49,6 +49,7 @@ public class AltosVoice {  	private Location	last_receiver;  	private long		last_speak_time;  	private int		last_flight_tell = TELL_FLIGHT_NONE; +	private boolean		quiet = false;  	private long now() {  		return System.currentTimeMillis(); @@ -80,7 +81,8 @@ public class AltosVoice {  	public synchronized void speak(String s) {  		if (!tts_enabled) return;  		last_speak_time = now(); -		tts.speak(s, TextToSpeech.QUEUE_ADD, null); +		if (!quiet) +			tts.speak(s, TextToSpeech.QUEUE_ADD, null);  	}  	public synchronized long time_since_speak() { @@ -121,6 +123,8 @@ public class AltosVoice {  		if (state == null)  			return false; +		AltosDebug.debug("tell_pad lag %b ltm %d\n", last_apogee_good, last_tell_mode); +  		if (state.apogee_voltage != AltosLib.MISSING)  			last_apogee_good = tell_gonogo("apogee",  						       state.apogee_voltage >= AltosLib.ao_igniter_good, @@ -239,12 +243,12 @@ public class AltosVoice {  		if (last_flight_tell == TELL_FLIGHT_HEIGHT) {  			last_flight_tell = TELL_FLIGHT_TRACK;  			if (from_receiver != null) { -				speak("bearing %s %d, elevation %d, range %s.", +				speak("bearing %s %d, elevation %d, distance %s.",  				      from_receiver.bearing_words(  					      AltosGreatCircle.BEARING_VOICE),  				      (int) (from_receiver.bearing + 0.5),  				      (int) (from_receiver.elevation + 0.5), -				      AltosConvert.distance.say(from_receiver.range)); +				      AltosConvert.distance.say(from_receiver.distance));  				return true;  			}  		} @@ -269,7 +273,7 @@ public class AltosVoice {  		if (direction == null)  			direction = String.format("Bearing %d", (int) (from_receiver.bearing + 0.5)); -		speak("%s, range %s.", direction, +		speak("%s, distance %s.", direction,  		      AltosConvert.distance.say_units(from_receiver.distance));  		return true; @@ -277,7 +281,9 @@ public class AltosVoice {  	public void tell(TelemetryState telem_state, AltosState state,  			 AltosGreatCircle from_receiver, Location receiver, -			 AltosDroidTab tab) { +			 AltosDroidTab tab, boolean quiet) { + +		this.quiet = quiet;  		boolean	spoken = false; @@ -288,7 +294,7 @@ public class AltosVoice {  		int	tell_serial = last_tell_serial;  		if (state != null) -			tell_serial = state.serial; +			tell_serial = state.cal_data().serial;  		if (tell_serial != last_tell_serial)  			reset_last(); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java index 7b3bbb4e..ace0a7d6 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java @@ -35,7 +35,7 @@ import android.view.View.OnClickListener;  import android.widget.*;  import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class IdleModeActivity extends Activity {  	private EditText callsign; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java index 4b8dc3e8..eccf5c59 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java @@ -33,7 +33,7 @@ import android.view.View.*;  import android.widget.*;  import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  class IgniterItem {  	public String name; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java index 0eef129e..ff599fda 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java @@ -33,7 +33,7 @@ import android.view.inputmethod.*;  import android.widget.*;  import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  class FrequencyItem {  	public AltosFrequency frequency; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java index a0c7233f..b93eaa19 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java @@ -35,7 +35,7 @@ import android.view.View.OnClickListener;  import android.widget.*;  import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class MapTypeActivity extends Activity {  	private Button hybrid; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java index a8e87bf2..9c43870f 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java @@ -42,7 +42,7 @@ import android.location.LocationManager;  import android.location.LocationListener;  import android.location.Criteria; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  /**   * This Activity appears as a dialog. It lists any paired devices and diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java index 41c3eb88..d970fc4f 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java @@ -31,7 +31,7 @@ import android.view.View.*;  import android.widget.*;  import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class SetupActivity extends Activity {  	private Spinner select_rate; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java index 3143679a..5349612c 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java @@ -18,7 +18,7 @@  package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import android.app.Activity;  import android.os.Bundle; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java index 5db5b85f..d239d988 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java @@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid;  import java.util.*;  import java.io.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import android.app.Activity;  import android.graphics.*; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java index 492f7f5f..ba5afba5 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java @@ -18,7 +18,7 @@  package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import android.app.Activity;  import android.os.Bundle; @@ -178,10 +178,10 @@ public class TabPad extends AltosDroidTab {  			}  			main_lights.set(state.main_voltage >= AltosLib.ao_igniter_good, state.main_voltage == AltosLib.MISSING); -			int num_igniter = state.ignitor_voltage == null ? 0 : state.ignitor_voltage.length; +			int num_igniter = state.igniter_voltage == null ? 0 : state.igniter_voltage.length;  			for (int i = 0; i < 4; i++) { -				double voltage = i >= num_igniter ? AltosLib.MISSING : state.ignitor_voltage[i]; +				double voltage = i >= num_igniter ? AltosLib.MISSING : state.igniter_voltage[i];  				if (voltage == AltosLib.MISSING) {  					ignite_row[i].setVisibility(View.GONE);  				} else { @@ -191,7 +191,7 @@ public class TabPad extends AltosDroidTab {  				ignite_lights[i].set(voltage >= AltosLib.ao_igniter_good, voltage == AltosLib.MISSING);  			} -			if (state.flight != 0) { +			if (state.cal_data().flight != 0) {  				if (state.state() <= AltosLib.ao_flight_pad)  					data_logging_view.setText("Ready to record");  				else if (state.state() < AltosLib.ao_flight_landed) @@ -201,7 +201,7 @@ public class TabPad extends AltosDroidTab {  			} else {  				data_logging_view.setText("Storage full");  			} -			data_logging_lights.set(state.flight != 0, state.flight == AltosLib.MISSING); +			data_logging_lights.set(state.cal_data().flight != 0, state.cal_data().flight == AltosLib.MISSING);  			if (state.gps != null) {  				int soln = state.gps.nsat; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java index 97a35c9e..ac211230 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java @@ -18,7 +18,7 @@  package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import android.app.Activity;  import android.os.Bundle; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java index c379d3d8..56f235c1 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java @@ -1,6 +1,6 @@  package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import android.content.BroadcastReceiver;  import android.content.Context; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java index bc0b3615..d097a550 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java @@ -26,7 +26,7 @@ import java.util.*;  import java.util.concurrent.*;  import android.os.Handler; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class TelemetryReader extends Thread { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 34c86ce5..caf288a0 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -41,7 +41,7 @@ import android.os.Looper;  import android.widget.Toast;  import android.location.Criteria; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class TelemetryService extends Service implements AltosIdleMonitorListener { @@ -259,14 +259,15 @@ public class TelemetryService extends Service implements AltosIdleMonitorListene  	private void telemetry(AltosTelemetry telem) {  		AltosState	state; -		if (telemetry_state.states.containsKey(telem.serial)) -			state = telemetry_state.states.get(telem.serial).clone(); +		if (telemetry_state.states.containsKey(telem.serial())) +			state = telemetry_state.states.get(telem.serial());  		else -			state = new AltosState(); -		telem.update_state(state); -		telemetry_state.states.put(telem.serial, state); +			state = new AltosState(new AltosCalData()); +		telem.provide_data(state); +		telemetry_state.states.put(telem.serial(), state); +		telemetry_state.quiet = false;  		if (state != null) { -			AltosPreferences.set_state(state); +			AltosPreferences.set_state(state,telem.serial());  		}  		send_to_clients();  	} @@ -615,6 +616,8 @@ public class TelemetryService extends Service implements AltosIdleMonitorListene  		telemetry_state.latest_serial = AltosPreferences.latest_state(); +		telemetry_state.quiet = true; +  		AltosDebug.debug("latest serial %d\n", telemetry_state.latest_serial);  		for (int serial : serials) { @@ -625,7 +628,7 @@ public class TelemetryService extends Service implements AltosIdleMonitorListene  				AltosDebug.debug("recovered old state serial %d flight %d",  						 serial, -						 saved_state.flight); +						 saved_state.cal_data().flight);  				if (saved_state.gps != null)  					AltosDebug.debug("\tposition %f,%f",  							 saved_state.gps.lat, @@ -699,7 +702,7 @@ public class TelemetryService extends Service implements AltosIdleMonitorListene  	/* AltosIdleMonitorListener */  	public void update(AltosState state, AltosListenerState listener_state)	{ -		telemetry_state.states.put(state.serial, state); +		telemetry_state.states.put(state.cal_data().serial, state);  		telemetry_state.receiver_battery = listener_state.battery;  		send_to_clients();  	} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java index 32ba1254..77cee787 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java @@ -19,7 +19,7 @@  package org.altusmetrum.AltosDroid;  import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import android.location.Location;  public class TelemetryState { @@ -36,6 +36,8 @@ public class TelemetryState {  	double		frequency;  	int		telemetry_rate; +	boolean		quiet; +  	HashMap<Integer,AltosState>	states;  	int		latest_serial; diff --git a/altoslib/AltosAccel.java b/altoslib/AltosAccel.java index 31aa7c1b..8fefefc5 100644 --- a/altoslib/AltosAccel.java +++ b/altoslib/AltosAccel.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosCRCException.java b/altoslib/AltosCRCException.java index 80dca140..5c398d3c 100644 --- a/altoslib/AltosCRCException.java +++ b/altoslib/AltosCRCException.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosCRCException extends Exception {  	public int rssi; diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java index b5199456..f55b4785 100644 --- a/altoslib/AltosCSV.java +++ b/altoslib/AltosCSV.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; @@ -27,16 +27,17 @@ public class AltosCSV implements AltosWriter {  	boolean			header_written;  	boolean			seen_boost;  	int			boost_tick; -	LinkedList<AltosState>	pad_states; -	AltosState		state; -	static boolean		has_basic; -	static boolean		has_battery; -	static boolean		has_flight_state; -	static boolean		has_advanced; -	static boolean		has_gps; -	static boolean		has_gps_sat; -	static boolean		has_companion; +	boolean			has_basic; +	boolean			has_battery; +	boolean			has_flight_state; +	boolean			has_advanced; +	boolean			has_gps; +	boolean			has_gps_sat; +	boolean			has_companion; + +	AltosFlightSeries	series; +	int[]			indices;  	static final int ALTOS_CSV_VERSION = 5; @@ -117,71 +118,116 @@ public class AltosCSV implements AltosWriter {  		out.printf("version,serial,flight,call,time,clock,rssi,lqi");  	} -	void write_general(AltosState state) { +	double time() { +		return series.time(indices); +	} + +	int rssi() { +		return (int) series.value(AltosFlightSeries.rssi_name, indices); +	} + +	int status() { +		return (int) series.value(AltosFlightSeries.status_name, indices); +	} + +	void write_general() { +		double time = time();  		out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d", -			   ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign, -			   (double) state.time_since_boost(), (double) state.tick / 100.0, -			   state.rssi, -			   state.status & 0x7f); +			   ALTOS_CSV_VERSION, series.cal_data().serial, +			   series.cal_data().flight, series.cal_data().callsign, +			   time, time, +			   rssi(), status() & 0x7f);  	}  	void write_flight_header() {  		out.printf("state,state_name");  	} -	void write_flight(AltosState state) { -		out.printf("%d,%8s", state.state(), state.state_name()); +	int state() { +		return (int) series.value(AltosFlightSeries.state_name, indices); +	} + +	void write_flight() { +		int state = state(); +		out.printf("%d,%8s", state, AltosLib.state_name(state));  	}  	void write_basic_header() {  		out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage");  	} -	void write_basic(AltosState state) { +	double acceleration() { return series.value(AltosFlightSeries.accel_name, indices); } +	double pressure() { return series.value(AltosFlightSeries.pressure_name, indices); } +	double altitude() { return series.value(AltosFlightSeries.altitude_name, indices); } +	double height() { return series.value(AltosFlightSeries.height_name, indices); } +	double speed() { return series.value(AltosFlightSeries.speed_name, indices); } +	double temperature() { return series.value(AltosFlightSeries.temperature_name, indices); } +	double apogee_voltage() { return series.value(AltosFlightSeries.apogee_voltage_name, indices); } +	double main_voltage() { return series.value(AltosFlightSeries.main_voltage_name, indices); } + +	void write_basic() {  		out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f", -			   state.acceleration(), -			   state.pressure(), -			   state.altitude(), -			   state.height(), -			   state.speed(), -			   state.speed(), -			   state.temperature, -			   state.apogee_voltage, -			   state.main_voltage); +			   acceleration(), +			   pressure(), +			   altitude(), +			   height(), +			   speed(), +			   speed(), +			   temperature(), +			   apogee_voltage(), +			   main_voltage());  	}  	void write_battery_header() {  		out.printf("battery_voltage");  	} -	void write_battery(AltosState state) { -		out.printf("%5.2f", state.battery_voltage); +	double battery_voltage() { return series.value(AltosFlightSeries.battery_voltage_name, indices); } + +	void write_battery() { +		out.printf("%5.2f", battery_voltage());  	}  	void write_advanced_header() {  		out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z");  	} -	void write_advanced(AltosState state) { +	double accel_along() { return series.value(AltosFlightSeries.accel_along_name, indices); } +	double accel_across() { return series.value(AltosFlightSeries.accel_across_name, indices); } +	double accel_through() { return series.value(AltosFlightSeries.accel_through_name, indices); } + +	double gyro_roll() { return series.value(AltosFlightSeries.gyro_roll_name, indices); } +	double gyro_pitch() { return series.value(AltosFlightSeries.gyro_pitch_name, indices); } +	double gyro_yaw() { return series.value(AltosFlightSeries.gyro_yaw_name, indices); } + +	double mag_along() { return series.value(AltosFlightSeries.mag_along_name, indices); } +	double mag_across() { return series.value(AltosFlightSeries.mag_across_name, indices); } +	double mag_through() { return series.value(AltosFlightSeries.mag_through_name, indices); } + +	void write_advanced() {  		out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f", -			   state.accel_along(), state.accel_across(), state.accel_through(), -			   state.gyro_roll(), state.gyro_pitch(), state.gyro_yaw(), -			   state.mag_along(), state.mag_across(), state.mag_through()); +			   accel_along(), accel_across(), accel_through(), +			   gyro_roll(), gyro_pitch(), gyro_yaw(), +			   mag_along(), mag_across(), mag_through());  	}  	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,pdop,hdop,vdop");  	} -	void write_gps(AltosState state) { -		AltosGPS	gps = state.gps; -		if (gps == null) -			gps = new AltosGPS(); +	void write_gps() { +		AltosGPS	gps = series.gps_before(series.time(indices)); + +		AltosGreatCircle from_pad; -		AltosGreatCircle from_pad = state.from_pad; -		if (from_pad == null) +		if (series.cal_data().gps_pad != null && gps != null) +			from_pad = new AltosGreatCircle(series.cal_data().gps_pad, gps); +		else  			from_pad = new AltosGreatCircle(); +		if (gps == null) +			gps = new AltosGPS(); +  		out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%8.1f,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f,%6.1f,%6.1f,%6.1f",  			   gps.connected?1:0,  			   gps.locked?1:0, @@ -196,9 +242,9 @@ public class AltosCSV implements AltosWriter {  			   gps.minute,  			   gps.second,  			   from_pad.distance, -			   state.range, +			   from_pad.range,  			   from_pad.bearing, -			   state.elevation, +			   from_pad.elevation,  			   gps.pdop,  			   gps.hdop,  			   gps.vdop); @@ -212,8 +258,8 @@ public class AltosCSV implements AltosWriter {  		}  	} -	void write_gps_sat(AltosState state) { -		AltosGPS	gps = state.gps; +	void write_gps_sat() { +		AltosGPS	gps = series.gps_before(series.time(indices));  		for(int i = 1; i <= 32; i++) {  			int	c_n0 = 0;  			if (gps != null && gps.cc_gps_sat != null) { @@ -230,12 +276,15 @@ public class AltosCSV implements AltosWriter {  	}  	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(AltosState state) { +	void write_companion() { +/*  		AltosCompanion companion = state.companion;  		int	channels_written = 0; @@ -252,6 +301,7 @@ public class AltosCSV implements AltosWriter {  		}  		for (; channels_written < 12; channels_written++)  			out.printf(",0"); +*/  	}  	void write_header() { @@ -287,63 +337,47 @@ public class AltosCSV implements AltosWriter {  		out.printf ("\n");  	} -	void write_one(AltosState state) { -		write_general(state); +	void write_one() { +		write_general();  		if (has_flight_state) {  			out.printf(","); -			write_flight(state); +			write_flight();  		}  		if (has_basic) {  			out.printf(","); -			write_basic(state); +			write_basic();  		}  		if (has_battery) {  			out.printf(","); -			write_battery(state); +			write_battery();  		}  		if (has_advanced) {  			out.printf(","); -			write_advanced(state); +			write_advanced();  		}  		if (has_gps) {  			out.printf(","); -			write_gps(state); +			write_gps();  		}  		if (has_gps_sat) {  			out.printf(","); -			write_gps_sat(state); +			write_gps_sat();  		}  		if (has_companion) {  			out.printf(","); -			write_companion(state); +			write_companion();  		}  		out.printf ("\n");  	} -	private void flush_pad() { -		while (!pad_states.isEmpty()) { -			write_one (pad_states.remove()); -		} -	} - -	private void write(AltosState state) { -		if (state.state() == AltosLib.ao_flight_startup) +	private void write() { +		if (state() == AltosLib.ao_flight_startup)  			return;  		if (!header_written) {  			write_header();  			header_written = true;  		} -		if (!seen_boost) { -			if (state.state() >= AltosLib.ao_flight_boost) { -				seen_boost = true; -				boost_tick = state.tick; -				flush_pad(); -			} -		} -		if (seen_boost) -			write_one(state); -		else -			pad_states.add(state); +		write_one();  	}  	private PrintStream out() { @@ -351,15 +385,15 @@ public class AltosCSV implements AltosWriter {  	}  	public void close() { -		if (!pad_states.isEmpty()) { -			boost_tick = pad_states.element().tick; -			flush_pad(); -		}  		out.close();  	} -	public void write(AltosStateIterable states) { -		states.write_comments(out()); +	public void write(AltosFlightSeries series) { +//		series.write_comments(out()); + +		this.series = series; + +		series.finish();  		has_flight_state = false;  		has_basic = false; @@ -368,31 +402,37 @@ public class AltosCSV implements AltosWriter {  		has_gps = false;  		has_gps_sat = false;  		has_companion = false; -		for (AltosState state : states) { -			if (state.state() != AltosLib.ao_flight_stateless && state.state() != AltosLib.ao_flight_invalid && state.state() != AltosLib.ao_flight_startup) -				has_flight_state = true; -			if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING) -				has_basic = true; -			if (state.battery_voltage != AltosLib.MISSING) -				has_battery = true; -			if (state.accel_across() != AltosLib.MISSING) -				has_advanced = true; -			if (state.gps != null) { -				has_gps = true; -				if (state.gps.cc_gps_sat != null) -					has_gps_sat = true; -			} -			if (state.companion != null) -				has_companion = true; + +		if (series.has_series(AltosFlightSeries.state_name)) +			has_flight_state = true; +		if (series.has_series(AltosFlightSeries.accel_name) || series.has_series(AltosFlightSeries.pressure_name)) +			has_basic = true; +		if (series.has_series(AltosFlightSeries.battery_voltage_name)) +			has_battery = true; +		if (series.has_series(AltosFlightSeries.accel_across_name)) +			has_advanced = true; + +		if (series.gps_series != null) +			has_gps = true; +		if (series.sats_in_view != null) +			has_gps_sat = true; +		/* +		if (state.companion != null) +			has_companion = true; +		*/ + +		indices = series.indices(); + +		for (;;) { +			write(); +			if (!series.step_indices(indices)) +				break;  		} -		for (AltosState state : states) -			write(state);  	}  	public AltosCSV(PrintStream in_out, File in_name) {  		name = in_name;  		out = in_out; -		pad_states = new LinkedList<AltosState>();  	}  	public AltosCSV(File in_name) throws FileNotFoundException { diff --git a/altoslib/AltosCalData.java b/altoslib/AltosCalData.java new file mode 100644 index 00000000..b49e3792 --- /dev/null +++ b/altoslib/AltosCalData.java @@ -0,0 +1,406 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +/* + * Calibration and other data needed to construct 'real' values from various data + * sources. + */ + +public class AltosCalData { +	public int		flight = AltosLib.MISSING; + +	public void set_flight(int flight) { +		if (flight != AltosLib.MISSING) +			this.flight = flight; +	} + +	public String		callsign = null; + +	public void set_callsign(String callsign) { +		if (callsign != null) +			this.callsign = callsign; +	} + +	public String		firmware_version = null; + +	public void set_firmware_version(String firmware_version) { +		if (firmware_version != null) +			this.firmware_version = firmware_version; +	} + +	public String		product = null; + +	public void set_product(String product) { +		if (product != null) +			this.product = product; +	} + +	public int		serial = AltosLib.MISSING; + +	public void set_serial(int serial) { +		if (serial != AltosLib.MISSING) +			this.serial = serial; +	} + +	public int		receiver_serial = AltosLib.MISSING; + +	public void set_receiver_serial(int receiver_serial) { +		if (receiver_serial != AltosLib.MISSING) +			this.receiver_serial = receiver_serial; +	} + +	public int		device_type = AltosLib.MISSING; + +	public void set_device_type(int device_type) { +		if (device_type != AltosLib.MISSING) { +			this.device_type = device_type; +			if (product == null) +				set_product(AltosLib.product_name(device_type)); +		} +	} + +	public int		config_major = AltosLib.MISSING; +	public int		config_minor = AltosLib.MISSING; +	public int		flight_log_max = AltosLib.MISSING; + +	public void set_config(int major, int minor, int log_max) { +		if (major != AltosLib.MISSING) +			config_major = major; +		if (minor != AltosLib.MISSING) +			config_minor = minor; +		if (log_max != AltosLib.MISSING) +			flight_log_max = log_max; +	} + +	public double		apogee_delay = AltosLib.MISSING; +	public double		main_deploy = AltosLib.MISSING; + +	public void set_flight_params(double apogee_delay, double main_deploy) { +		if (apogee_delay != AltosLib.MISSING) +			this.apogee_delay = apogee_delay; +		if (main_deploy != AltosLib.MISSING) +			this.main_deploy = main_deploy; +	} + +	public double		accel_plus_g = AltosLib.MISSING; +	public double		accel_minus_g = AltosLib.MISSING; +	public double		ground_accel = AltosLib.MISSING; + +	public void set_accel_plus_minus(double plus, double minus) { +		if (plus != AltosLib.MISSING && minus != AltosLib.MISSING) { +			if (plus == minus) +				return; +			accel_plus_g = plus; +			accel_minus_g = minus; +		} +	} + +	public void set_ground_accel(double ground_accel) { +		if (ground_accel != AltosLib.MISSING) +			this.ground_accel = ground_accel; +	} + +	/* Raw acceleration value */ +	public double		accel = AltosLib.MISSING; + +	public void set_accel(double accel) { +		this.accel = accel; +	} + +	public boolean mma655x_inverted = false; + +	public void set_mma655x_inverted(boolean inverted) { +		mma655x_inverted = inverted; +	} + +	public int pad_orientation = AltosLib.MISSING; + +	public void set_pad_orientation(int orientation) { +		if (orientation != AltosLib.MISSING) +			pad_orientation = orientation; +	} + +	/* Compute acceleration */ +	public double acceleration(double sensor) { +		return AltosConvert.acceleration_from_sensor(sensor, accel_plus_g, accel_minus_g, ground_accel); +	} + +	public AltosMs5607	ms5607 = null; + +	public void set_ms5607(AltosMs5607 ms5607) { +		this.ms5607 = ms5607; +	} + +	public double		ground_pressure = AltosLib.MISSING; +	public double		ground_altitude = AltosLib.MISSING; + +	public void set_ground_pressure(double ground_pressure) { +		if (ground_pressure != AltosLib.MISSING) { +			this.ground_pressure = ground_pressure; +			this.ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); +		} +	} + +	public void set_ground_altitude(double ground_altitude) { +		if (ground_altitude != AltosLib.MISSING) +			this.ground_altitude = ground_altitude; +	} + +	/* Compute pressure */ + +	public AltosPresTemp pressure_ms5607(int raw_pres, int raw_temp) { +		if (ms5607 == null) +			return new AltosPresTemp(AltosLib.MISSING, AltosLib.MISSING); +		return ms5607.pres_temp(raw_pres, raw_temp); +	} + +	public int		tick = AltosLib.MISSING; +	private int		first_tick = AltosLib.MISSING; +	private int		prev_tick = AltosLib.MISSING; + +	public void set_tick(int tick) { +		if (tick != AltosLib.MISSING) { +			if (prev_tick != AltosLib.MISSING) { +				while (tick < prev_tick - 1000) { +					tick += 65536; +				} +			} +			if (first_tick == AltosLib.MISSING) +				first_tick = tick; +			prev_tick = tick; +			this.tick = tick; +		} +	} + +	/* Reset all values which change during flight +	 */ +	public void reset() { +		state = AltosLib.MISSING; +		tick = AltosLib.MISSING; +		prev_tick = AltosLib.MISSING; +		temp_gps = null; +		prev_gps = null; +		temp_gps_sat_tick = AltosLib.MISSING; +		accel = AltosLib.MISSING; +	} + +	public int		boost_tick = AltosLib.MISSING; + +	public void set_boost_tick() { +		boost_tick = tick; +	} + +	public double		ticks_per_sec = 100.0; + +	public void set_ticks_per_sec(double ticks_per_sec) { +		this.ticks_per_sec = ticks_per_sec; +	} + +	public double time() { +		if (tick == AltosLib.MISSING) +			return AltosLib.MISSING; +		if (boost_tick != AltosLib.MISSING) +			return (tick - boost_tick) / ticks_per_sec; +		if (first_tick != AltosLib.MISSING) +			return (tick - first_tick) / ticks_per_sec; +		return tick / ticks_per_sec; +	} + +	public double boost_time() { +		if (boost_tick == AltosLib.MISSING) +			return AltosLib.MISSING; +		return boost_tick / ticks_per_sec; +	} + +	public int		state = AltosLib.MISSING; + +	public void set_state(int state) { +		if (state >= AltosLib.ao_flight_boost && boost_tick == AltosLib.MISSING) +			set_boost_tick(); +		this.state = state; +	} + +	public AltosGPS		gps_pad = null; + +	public double		gps_pad_altitude = AltosLib.MISSING; + +	public void set_gps(AltosGPS gps) { +		if ((state != AltosLib.MISSING && state < AltosLib.ao_flight_boost) || gps_pad == null) +			gps_pad = gps; +		if (gps_pad_altitude == AltosLib.MISSING && gps.alt != AltosLib.MISSING) +			gps_pad_altitude = gps.alt; +	} + +	/* +	 * While receiving GPS data, we construct a temporary GPS state +	 * object and then deliver the result atomically to the listener +	 */ +	AltosGPS		temp_gps = null; +	AltosGPS		prev_gps = null; +	int			temp_gps_sat_tick = AltosLib.MISSING; + +	public AltosGPS temp_gps() { +		return temp_gps; +	} + +	public void reset_temp_gps() { +		if (temp_gps != null) { +			if (temp_gps.locked && temp_gps.nsat >= 4) +				set_gps(temp_gps); +			prev_gps = temp_gps; +			temp_gps = null; +		} +	} + +	public boolean gps_pending() { +		return temp_gps != null; +	} + +	public AltosGPS make_temp_gps(int tick, boolean sats) { +		if (temp_gps == null) { +			if (prev_gps != null) +				temp_gps = prev_gps.clone(); +			else +				temp_gps = new AltosGPS(); +		} +		if (sats) { +			if (tick != temp_gps_sat_tick) +				temp_gps.cc_gps_sat = null; +			temp_gps_sat_tick = tick; +		} +		return temp_gps; +	} + +	public double	accel_zero_along, accel_zero_across, accel_zero_through; + +	public void set_accel_zero(double zero_along, double zero_across, double zero_through) { +		if (zero_along != AltosLib.MISSING) { +			accel_zero_along = zero_along; +			accel_zero_across = zero_across; +			accel_zero_through = zero_through; +		} +	} + +	public double accel_along(double counts) { +		return AltosIMU.convert_accel(counts - accel_zero_along); +	} + +	public double accel_across(double counts) { +		return AltosIMU.convert_accel(counts - accel_zero_across); +	} + +	public double accel_through(double counts) { +		return AltosIMU.convert_accel(counts - accel_zero_through); +	} + +	public double	gyro_zero_roll,	gyro_zero_pitch, gyro_zero_yaw; + +	public void set_gyro_zero(double roll, double pitch, double yaw) { +		if (roll != AltosLib.MISSING) { +			gyro_zero_roll = roll; +			gyro_zero_pitch = pitch; +			gyro_zero_yaw = yaw; +			imu_wrap_checked = false; +		} +	} + +	public double gyro_roll(double counts) { +		if (gyro_zero_roll == AltosLib.MISSING || counts == AltosLib.MISSING) +			return AltosLib.MISSING; + +		return AltosIMU.gyro_degrees_per_second(counts, gyro_zero_roll); +	} + +	public double gyro_pitch(double counts) { +		if (gyro_zero_pitch == AltosLib.MISSING || counts == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosIMU.gyro_degrees_per_second(counts, gyro_zero_pitch); +	} + +	public double gyro_yaw(double counts) { +		if (gyro_zero_yaw == AltosLib.MISSING || counts == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosIMU.gyro_degrees_per_second(counts, gyro_zero_yaw); +	} + +	private double gyro_zero_overflow(double first) { +		double v = first / 128.0; +		if (v < 0) +			v = Math.ceil(v); +		else +			v = Math.floor(v); +		if (v != 0) +			System.out.printf("Adjusting gyro axis by %g steps\n", v); +		return v * 128.0; +	} + +	/* Initial TeleMega log format had only 16 bits for gyro cal, so the top 9 bits got lost as the +	 * cal data are scaled by 512. Use the first sample to adjust the cal value, assuming that it is +	 * from a time of fairly low rotation speed. Fixed in later TeleMega firmware by storing 32 bits +	 * of cal values. +	 */ +	private boolean imu_wrap_checked = false; + +	public void check_imu_wrap(double roll, double pitch, double yaw) { +		if (!imu_wrap_checked) { +			gyro_zero_roll += gyro_zero_overflow(roll); +			gyro_zero_pitch += gyro_zero_overflow(pitch); +			gyro_zero_yaw += gyro_zero_overflow(yaw); +			imu_wrap_checked = true; +		} +	} + +	public double mag_along(double along) { +		if (along == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosMag.convert_gauss(along); +	} + +	public double mag_across(double across) { +		if (across == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosMag.convert_gauss(across); +	} + +	public double mag_through(double through) { +		if (through == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosMag.convert_gauss(through); +	} + +	public AltosCalData() { +	} + +	public AltosCalData(AltosConfigData config_data) { +		set_serial(config_data.serial); +		set_ticks_per_sec(100.0); +		set_flight(config_data.flight); +		set_callsign(config_data.callsign); +		set_config(config_data.config_major, config_data.config_minor, config_data.flight_log_max); +		set_firmware_version(config_data.version); +		set_flight_params(config_data.apogee_delay / ticks_per_sec, config_data.apogee_lockout / ticks_per_sec); +		set_pad_orientation(config_data.pad_orientation); +		set_product(config_data.product); +		set_accel_plus_minus(config_data.accel_cal_plus, config_data.accel_cal_minus); +		set_accel_zero(config_data.accel_zero_along, config_data.accel_zero_across, config_data.accel_zero_through); +		set_ms5607(config_data.ms5607); +		try { +			set_mma655x_inverted(config_data.mma655x_inverted()); +		} catch (AltosUnknownProduct up) { +		} +		set_pad_orientation(config_data.pad_orientation); +	} +} diff --git a/altoslib/AltosCompanion.java b/altoslib/AltosCompanion.java index 2c03c922..5ce333f8 100644 --- a/altoslib/AltosCompanion.java +++ b/altoslib/AltosCompanion.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 6b55cc6f..97a80bcb 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.*;  import java.text.*;  import java.util.concurrent.*; -public class AltosConfigData implements Iterable<String> { +public class AltosConfigData {  	/* Version information */  	public String	manufacturer; @@ -33,9 +33,7 @@ public class AltosConfigData implements Iterable<String> {  	public int	log_space;  	public String	version;  	public int	altitude_32; - -	/* Strings returned */ -	public LinkedList<String>	lines; +	public int	config_major, config_minor;  	/* Config information */  	/* HAS_FLIGHT*/ @@ -96,14 +94,13 @@ public class AltosConfigData implements Iterable<String> {  	public int	accel_zero_along, accel_zero_across, accel_zero_through;  	/* ms5607 data */ -	public int	ms5607_reserved; -	public int	ms5607_sens; -	public int	ms5607_off; -	public int	ms5607_tcs; -	public int	ms5607_tco; -	public int	ms5607_tref; -	public int	ms5607_tempsens; -	public int	ms5607_crc; +	AltosMs5607	ms5607; + +	public AltosMs5607 ms5607() { +		if (ms5607 == null) +			ms5607 = new AltosMs5607(); +		return ms5607; +	}  	public static String get_string(String line, String label) throws  ParseException {  		if (line.startsWith(label)) { @@ -142,21 +139,17 @@ public class AltosConfigData implements Iterable<String> {  		throw new ParseException("mismatch", 0);  	} -	public Iterator<String> iterator() { -		return lines.iterator(); -	} -  	public int log_space() { -		if (log_space > 0) +		if (log_space != AltosLib.MISSING)  			return log_space; -		if (storage_size > 0) { +		if (storage_size != AltosLib.MISSING) {  			int	space = storage_size; -			if (storage_erase_unit > 0 && use_flash_for_config()) +			if (storage_erase_unit != AltosLib.MISSING && use_flash_for_config())  				space -= storage_erase_unit; -			if (space > 0) +			if (space != AltosLib.MISSING)  				return space;  		}  		return 0; @@ -214,6 +207,10 @@ public class AltosConfigData implements Iterable<String> {  		return r;  	} +	public boolean altitude_32() { +		return altitude_32 == 1; +	} +  	public int compare_version(String other) {  		int[]	me = parse_version(version);  		int[]	them = parse_version(other); @@ -233,63 +230,63 @@ public class AltosConfigData implements Iterable<String> {  	}  	public void reset() { -		lines = new LinkedList<String>(); - -		manufacturer = "unknown"; -		product = "unknown"; -		serial = 0; -		flight = 0; +		manufacturer = null; +		product = null; +		serial = AltosLib.MISSING; +		flight = AltosLib.MISSING;  		log_format = AltosLib.AO_LOG_FORMAT_UNKNOWN; -		log_space = -1; +		log_space = AltosLib.MISSING;  		version = "unknown"; +		config_major = AltosLib.MISSING; +		config_minor = AltosLib.MISSING; -		main_deploy = -1; -		apogee_delay = -1; -		apogee_lockout = -1; +		main_deploy = AltosLib.MISSING; +		apogee_delay = AltosLib.MISSING; +		apogee_lockout = AltosLib.MISSING; -		radio_frequency = -1; +		radio_frequency = AltosLib.MISSING;  		callsign = null; -		radio_enable = -1; -		radio_calibration = -1; -		radio_channel = -1; -		radio_setting = -1; -		telemetry_rate = -1; +		radio_enable = AltosLib.MISSING; +		radio_calibration = AltosLib.MISSING; +		radio_channel = AltosLib.MISSING; +		radio_setting = AltosLib.MISSING; +		telemetry_rate = AltosLib.MISSING; -		accel_cal_plus = -1; -		accel_cal_minus = -1; -		pad_orientation = -1; +		accel_cal_plus = AltosLib.MISSING; +		accel_cal_minus = AltosLib.MISSING; +		pad_orientation = AltosLib.MISSING; -		flight_log_max = -1; -		log_fixed = -1; -		ignite_mode = -1; +		flight_log_max = AltosLib.MISSING; +		log_fixed = AltosLib.MISSING; +		ignite_mode = AltosLib.MISSING; -		aes_key = ""; +		aes_key = null; -		pyro = 0; -		npyro = 0; +		pyro = AltosLib.MISSING; +		npyro = AltosLib.MISSING;  		pyros = null; -		pyro_firing_time = -1; +		pyro_firing_time = AltosLib.MISSING; -		aprs_interval = -1; -		aprs_ssid = -1; -		aprs_format = -1; +		aprs_interval = AltosLib.MISSING; +		aprs_ssid = AltosLib.MISSING; +		aprs_format = AltosLib.MISSING; -		beep = -1; +		beep = AltosLib.MISSING; -		tracker_motion = -1; -		tracker_interval = -1; +		tracker_motion = AltosLib.MISSING; +		tracker_interval = AltosLib.MISSING; -		storage_size = -1; -		storage_erase_unit = -1; -		stored_flight = 0; +		storage_size = AltosLib.MISSING; +		storage_erase_unit = AltosLib.MISSING; +		stored_flight = AltosLib.MISSING; -		accel_zero_along = -1; -		accel_zero_across = -1; -		accel_zero_through = -1; +		accel_zero_along = AltosLib.MISSING; +		accel_zero_across = AltosLib.MISSING; +		accel_zero_through = AltosLib.MISSING;  	}  	public void parse_line(String line) { -		lines.add(line); +  		/* Version replies */  		try { manufacturer = get_string(line, "manufacturer"); } catch (Exception e) {}  		try { product = get_string(line, "product"); } catch (Exception e) {} @@ -302,17 +299,31 @@ public class AltosConfigData implements Iterable<String> {  		/* Version also contains MS5607 info, which we ignore here */ -		try { ms5607_reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {} -		try { ms5607_sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {} -		try { ms5607_off = get_int(line, "ms5607 off:"); } catch (Exception e) {} -		try { ms5607_tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {} -		try { ms5607_tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {} -		try { ms5607_tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {} -		try { ms5607_tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {} -		try { ms5607_crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {} +		try { ms5607().reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {} +		try { ms5607().sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {} +		try { ms5607().off = get_int(line, "ms5607 off:"); } catch (Exception e) {} +		try { ms5607().tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {} +		try { ms5607().tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {} +		try { ms5607().tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {} +		try { ms5607().tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {} +		try { ms5607().crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {}  		/* Config show replies */ +		try { +			if (line.startsWith("Config version")) { +				String[] bits = line.split("\\s+"); +				if (bits.length >= 3) { +					String[] cfg = bits[2].split("\\."); + +					if (cfg.length >= 2) { +						config_major = Integer.parseInt(cfg[0]); +						config_minor = Integer.parseInt(cfg[1]); +					} +				} +			} +		} catch (Exception e) {} +  		/* HAS_FLIGHT */  		try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {}  		try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} @@ -361,7 +372,7 @@ public class AltosConfigData implements Iterable<String> {  			pyros = new AltosPyro[npyro];  			pyro = 0;  		} catch (Exception e) {} -		if (npyro > 0) { +		if (npyro != AltosLib.MISSING) {  			try {  				AltosPyro p = new AltosPyro(pyro, line);  				if (pyro < npyro) @@ -425,24 +436,23 @@ public class AltosConfigData implements Iterable<String> {  	}  	public boolean has_frequency() { -		return radio_frequency >= 0 || radio_setting >= 0 || radio_channel >= 0; +		return radio_frequency != AltosLib.MISSING || radio_setting != AltosLib.MISSING || radio_channel != AltosLib.MISSING;  	}  	public boolean has_telemetry_rate() { -		return telemetry_rate >= 0; +		return telemetry_rate != AltosLib.MISSING;  	}  	public void set_frequency(double freq) {  		int	frequency = radio_frequency;  		int	setting = radio_setting; -		if (frequency > 0) { +		if (frequency != AltosLib.MISSING) {  			radio_frequency = (int) Math.floor (freq * 1000 + 0.5); -			radio_channel = -1; -		} else if (setting > 0) { -			radio_setting =AltosConvert.radio_frequency_to_setting(freq, -										    radio_calibration); -			radio_channel = -1; +			radio_channel = AltosLib.MISSING; +		} else if (setting != AltosLib.MISSING) { +			radio_setting =AltosConvert.radio_frequency_to_setting(freq, radio_calibration); +			radio_channel = AltosLib.MISSING;  		} else {  			radio_channel = AltosConvert.radio_frequency_to_channel(freq);  		} @@ -452,12 +462,12 @@ public class AltosConfigData implements Iterable<String> {  		int	channel = radio_channel;  		int	setting = radio_setting; -		if (radio_frequency < 0 && channel < 0 && setting < 0) -			return -1; +		if (radio_frequency == AltosLib.MISSING && channel == AltosLib.MISSING && setting == AltosLib.MISSING) +			return AltosLib.MISSING; -		if (channel < 0) +		if (channel == AltosLib.MISSING)  			channel = 0; -		if (setting < 0) +		if (setting == AltosLib.MISSING)  			setting = 0;  		return AltosConvert.radio_to_frequency(radio_frequency, @@ -492,56 +502,56 @@ public class AltosConfigData implements Iterable<String> {  	public void get_values(AltosConfigValues source) throws AltosConfigDataException {  		/* HAS_FLIGHT */ -		if (main_deploy >= 0) +		if (main_deploy != AltosLib.MISSING)  			main_deploy = source.main_deploy(); -		if (apogee_delay >= 0) +		if (apogee_delay != AltosLib.MISSING)  			apogee_delay = source.apogee_delay(); -		if (apogee_lockout >= 0) +		if (apogee_lockout != AltosLib.MISSING)  			apogee_lockout = source.apogee_lockout();  		/* HAS_RADIO */  		if (has_frequency())  			set_frequency(source.radio_frequency()); -		if (radio_enable >= 0) +		if (radio_enable != AltosLib.MISSING)  			radio_enable = source.radio_enable();  		if (callsign != null)  			callsign = source.callsign(); -		if (telemetry_rate >= 0) +		if (telemetry_rate != AltosLib.MISSING)  			telemetry_rate = source.telemetry_rate();  		/* HAS_ACCEL */ -		if (pad_orientation >= 0) +		if (pad_orientation != AltosLib.MISSING)  			pad_orientation = source.pad_orientation();  		/* HAS_LOG */ -		if (flight_log_max >= 0) +		if (flight_log_max != AltosLib.MISSING)  			flight_log_max = source.flight_log_max();  		/* HAS_IGNITE */ -		if (ignite_mode >= 0) +		if (ignite_mode != AltosLib.MISSING)  			ignite_mode = source.ignite_mode();  		/* AO_PYRO_NUM */ -		if (npyro > 0) +		if (npyro != AltosLib.MISSING)  			pyros = source.pyros(); -		if (pyro_firing_time >= 0) +		if (pyro_firing_time != AltosLib.MISSING)  			pyro_firing_time = source.pyro_firing_time();  		/* HAS_APRS */ -		if (aprs_interval >= 0) +		if (aprs_interval != AltosLib.MISSING)  			aprs_interval = source.aprs_interval(); -		if (aprs_ssid >= 0) +		if (aprs_ssid != AltosLib.MISSING)  			aprs_ssid = source.aprs_ssid(); -		if (aprs_format >= 0) +		if (aprs_format != AltosLib.MISSING)  			aprs_format = source.aprs_format();  		/* HAS_BEEP */ -		if (beep >= 0) +		if (beep != AltosLib.MISSING)  			beep = source.beep();  		/* HAS_TRACKER */ -		if (tracker_motion >= 0) +		if (tracker_motion != AltosLib.MISSING)  			tracker_motion = source.tracker_motion(); -		if (tracker_interval >= 0) +		if (tracker_interval != AltosLib.MISSING)  			tracker_interval = source.tracker_interval();  	} @@ -561,7 +571,7 @@ public class AltosConfigData implements Iterable<String> {  		if (log_space() == 0)  			max_enabled = false; -		if (log_fixed > 0) +		if (log_fixed != AltosLib.MISSING)  			max_enabled = false;  		switch (log_format) { @@ -569,7 +579,7 @@ public class AltosConfigData implements Iterable<String> {  			max_enabled = false;  			break;  		default: -			if (stored_flight > 0) +			if (stored_flight != AltosLib.MISSING)  				max_enabled = false;  			break;  		} @@ -581,7 +591,7 @@ public class AltosConfigData implements Iterable<String> {  		dest.set_ignite_mode(ignite_mode);  		dest.set_pad_orientation(pad_orientation);  		dest.set_callsign(callsign); -		if (npyro > 0) +		if (npyro != AltosLib.MISSING)  			dest.set_pyros(pyros);  		else  			dest.set_pyros(null); @@ -605,17 +615,17 @@ public class AltosConfigData implements Iterable<String> {  	public void save(AltosLink link, boolean remote) throws InterruptedException, TimeoutException {  		/* HAS_FLIGHT */ -		if (main_deploy >= 0) +		if (main_deploy != AltosLib.MISSING)  			link.printf("c m %d\n", main_deploy); -		if (apogee_delay >= 0) +		if (apogee_delay != AltosLib.MISSING)  			link.printf("c d %d\n", apogee_delay); -		if (apogee_lockout >= 0) +		if (apogee_lockout != AltosLib.MISSING)  			link.printf("c L %d\n", apogee_lockout);  		/* HAS_RADIO */  		if (has_frequency()) { -			boolean has_frequency = radio_frequency >= 0; -			boolean has_setting = radio_setting > 0; +			boolean has_frequency = radio_frequency != AltosLib.MISSING; +			boolean has_setting = radio_setting != AltosLib.MISSING;  			double frequency = frequency();  			link.set_radio_frequency(frequency,  							has_frequency, @@ -631,7 +641,7 @@ public class AltosConfigData implements Iterable<String> {  			}  		} -		if (telemetry_rate >= 0) { +		if (telemetry_rate != AltosLib.MISSING) {  			link.printf("c T %d\n", telemetry_rate);  			if (remote) {  				link.flush_output(); @@ -653,12 +663,12 @@ public class AltosConfigData implements Iterable<String> {  			}  		} -		if (radio_enable >= 0) +		if (radio_enable != AltosLib.MISSING)  			link.printf("c e %d\n", radio_enable);  		/* HAS_ACCEL */  		/* UI doesn't support accel cal */ -		if (pad_orientation >= 0) +		if (pad_orientation != AltosLib.MISSING)  			link.printf("c o %d\n", pad_orientation);  		/* HAS_LOG */ @@ -666,36 +676,36 @@ public class AltosConfigData implements Iterable<String> {  			link.printf("c l %d\n", flight_log_max);  		/* HAS_IGNITE */ -		if (ignite_mode >= 0) +		if (ignite_mode != AltosLib.MISSING)  			link.printf("c i %d\n", ignite_mode);  		/* HAS_AES */  		/* UI doesn't support AES key config */  		/* AO_PYRO_NUM */ -		if (npyro > 0) { +		if (npyro != AltosLib.MISSING) {  			for (int p = 0; p < pyros.length; p++) {  				link.printf("c P %s\n",  						   pyros[p].toString());  			}  		} -		if (pyro_firing_time >= 0) +		if (pyro_firing_time != AltosLib.MISSING)  			link.printf("c I %d\n", (int) (pyro_firing_time * 100.0 + 0.5));  		/* HAS_APRS */ -		if (aprs_interval >= 0) +		if (aprs_interval != AltosLib.MISSING)  			link.printf("c A %d\n", aprs_interval); -		if (aprs_ssid >= 0) +		if (aprs_ssid != AltosLib.MISSING)  			link.printf("c S %d\n", aprs_ssid); -		if (aprs_format >= 0) +		if (aprs_format != AltosLib.MISSING)  			link.printf("c C %d\n", aprs_format);  		/* HAS_BEEP */ -		if (beep >= 0) +		if (beep != AltosLib.MISSING)  			link.printf("c b %d\n", beep);  		/* HAS_TRACKER */ -		if (tracker_motion >= 0 && tracker_interval >= 0) +		if (tracker_motion != AltosLib.MISSING && tracker_interval != AltosLib.MISSING)  			link.printf("c t %d %d\n", tracker_motion, tracker_interval);  		/* HAS_GYRO */ @@ -719,5 +729,4 @@ public class AltosConfigData implements Iterable<String> {  			break;  		}  	} -  } diff --git a/altoslib/AltosConfigDataException.java b/altoslib/AltosConfigDataException.java index 59a8e9c1..fe6336b6 100644 --- a/altoslib/AltosConfigDataException.java +++ b/altoslib/AltosConfigDataException.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosConfigDataException extends Exception { diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java index bc20d21d..170b1112 100644 --- a/altoslib/AltosConfigValues.java +++ b/altoslib/AltosConfigValues.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosConfigValues {  	/* set and get all of the dialog values */ diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 8617a12c..ed16541a 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -19,9 +19,14 @@  /*   * Sensor data conversion functions   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; + +import java.util.*;  public class AltosConvert { + +	public static final double gravity = 9.80665; +  	/*  	 * Pressure Sensor Model, version 1.1  	 * @@ -42,20 +47,20 @@ public class AltosConvert {  	 *   in Joules/(kilogram-Kelvin).  	 */ -	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; +	private static final double GRAVITATIONAL_ACCELERATION = -gravity; +	private static final double AIR_GAS_CONSTANT		= 287.053; +	private static final double NUMBER_OF_LAYERS		= 7; +	private static final double MAXIMUM_ALTITUDE		= 84852.0; +	private static final double MINIMUM_PRESSURE		= 0.3734; +	private static final double LAYER0_BASE_TEMPERATURE	= 288.15; +	private static final double LAYER0_BASE_PRESSURE	= 101325;  	/* lapse rate and base altitude for each layer in the atmosphere */ -	public static final double[] lapse_rate = { +	private static final double[] lapse_rate = {  		-0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002  	}; -	public static final int[] base_altitude = { +	private static final int[] base_altitude = {  		0, 11000, 20000, 32000, 47000, 51000, 71000  	}; @@ -179,6 +184,18 @@ public class AltosConvert {  		return altitude;  	} +	public static double degrees_to_radians(double degrees) { +		if (degrees == AltosLib.MISSING) +			return AltosLib.MISSING; +		return degrees * (Math.PI / 180.0); +	} + +	public static double radians_to_degrees(double radians) { +		if (radians == AltosLib.MISSING) +			return AltosLib.MISSING; +		return radians * (180.0 / Math.PI); +	} +  	public static double  	cc_battery_to_voltage(double battery)  	{ @@ -186,7 +203,7 @@ public class AltosConvert {  	}  	public static double -	cc_ignitor_to_voltage(double ignite) +	cc_igniter_to_voltage(double ignite)  	{  		return ignite / 32767 * 15.0;  	} @@ -253,7 +270,15 @@ public class AltosConvert {  		return 3.3 * mega_adc(raw) * (5.1 + 10.0) / 10.0;  	} -	static double easy_mini_voltage(int sensor, int serial) { +	static double easy_mini_2_adc(int raw) { +		return raw / 4095.0; +	} + +	static double easy_mini_1_adc(int raw) { +		return raw / 32767.0; +	} + +	static double easy_mini_1_voltage(int sensor, int serial) {  		double	supply = 3.3;  		double	diode_offset = 0.0; @@ -267,7 +292,13 @@ public class AltosConvert {  		if (serial < 1665)  			diode_offset = 0.150; -		return sensor / 32767.0 * supply * 127/27 + diode_offset; +		return easy_mini_1_adc(sensor) * supply * 127/27 + diode_offset; +	} + +	static double easy_mini_2_voltage(int sensor) { +		double	supply = 3.3; + +		return easy_mini_2_adc(sensor) * supply * 127/27;  	}  	public static double radio_to_frequency(int freq, int setting, int cal, int channel) { @@ -305,6 +336,10 @@ public class AltosConvert {  		return 434.550 + channel * 0.100;  	} +	public static int telem_to_rssi(int telem) { +		return telem / 2 - 74; +	} +  	public static int[] ParseHex(String line) {  		String[] tokens = line.split("\\s+");  		int[] array = new int[tokens.length]; @@ -370,12 +405,48 @@ public class AltosConvert {  		return psi * 6894.76;  	} +	public static double pa_to_psi(double pa) { +		return pa / 6894.76; +	} + +	public static double n_to_lb(double n) { +		return n * 0.22480894; +	} + +	public static double lb_to_n(double lb) { +		return lb / 0.22480894; +	} + +	public static double acceleration_from_sensor(double sensor, double plus_g, double minus_g, double ground) { + +		if (sensor == AltosLib.MISSING) +			return AltosLib.MISSING; + +		if (plus_g == AltosLib.MISSING || minus_g == AltosLib.MISSING) +			return AltosLib.MISSING; + +		if (ground == AltosLib.MISSING) +			ground = plus_g; + +		double counts_per_g = (plus_g - minus_g) / 2.0; +		double counts_per_mss = counts_per_g / gravity; + +		if (counts_per_mss == 0) +			return AltosLib.MISSING; + +		return (sensor - ground) / counts_per_mss; +	} +  	public static boolean imperial_units = false;  	public static AltosDistance distance = new AltosDistance();  	public static AltosHeight height = new AltosHeight(); +	public static AltosPressure pressure = new AltosPressure(); + +	public static AltosForce force = new AltosForce(); +  	public static AltosSpeed speed = new AltosSpeed();  	public static AltosAccel accel = new AltosAccel(); @@ -390,6 +461,14 @@ public class AltosConvert {  	public static AltosLongitude longitude = new AltosLongitude(); +	public static AltosRotationRate rotation_rate = new AltosRotationRate(); + +	public static AltosStateName state_name = new AltosStateName(); + +	public static AltosPyroName pyro_name = new AltosPyroName(); + +	public static AltosUnits magnetic_field = null; +  	public static String show_gs(String format, double a) {  		a = meters_to_g(a);  		format = format.concat(" g"); @@ -407,6 +486,13 @@ public class AltosConvert {  		return csum & 0xff;  	} +	public static int checksum(List<Byte> data, int start, int length) { +		int	csum = 0x5a; +		for (int i = 0; i < length; i++) +			csum += data.get(i+start); +		return csum & 0xff; +	} +  	public static double beep_value_to_freq(int value) {  		if (value == 0)  			return 4000; diff --git a/altoslib/AltosDataListener.java b/altoslib/AltosDataListener.java new file mode 100644 index 00000000..5f89b3e4 --- /dev/null +++ b/altoslib/AltosDataListener.java @@ -0,0 +1,95 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public abstract class AltosDataListener { + +	private AltosCalData	cal_data = null; + +	public double		time = AltosLib.MISSING; +	public int		state = AltosLib.MISSING; + +	public void set_tick(int tick) { +		cal_data.set_tick(tick); +		set_time(cal_data.time()); +	} + +	public AltosCalData cal_data() { +		if (cal_data == null) +			cal_data = new AltosCalData(); +		return cal_data; +	} + +	public void set_time(double time) { +		if (time != AltosLib.MISSING) +			this.time = time; +	} + +	public void set_serial(int serial) { +		cal_data().set_serial(serial); +	} + +	public double time() { +		return time; +	} + +	public void set_state(int state) { +		cal_data().set_state(state); +		if (state != AltosLib.MISSING) +			this.state = state; +	} + +	public void set_flight(int flight) { +		cal_data().set_flight(flight); +	} + +	/* Called after all records are captured */ +	public void finish() { +	} + +	public abstract void set_rssi(int rssi, int status); +	public abstract void set_received_time(long received_time); + +	public abstract void set_acceleration(double accel); +	public abstract void set_pressure(double pa); +	public abstract void set_thrust(double N); + +	public abstract void set_kalman(double height, double speed, double accel); + +	public abstract void set_temperature(double deg_c); +	public abstract void set_battery_voltage(double volts); + +	public abstract void set_apogee_voltage(double volts); +	public abstract void set_main_voltage(double volts); + +	public abstract void set_gps(AltosGPS gps); + +	public abstract void set_orient(double orient); +	public abstract void set_gyro(double roll, double pitch, double yaw); +	public abstract void set_accel_ground(double along, double across, double through); +	public abstract void set_accel(double along, double across, double through); +	public abstract void set_mag(double along, double across, double through); +	public abstract void set_pyro_voltage(double volts); +	public abstract void set_igniter_voltage(double[] voltage); +	public abstract void set_pyro_fired(int pyro_mask); +	public abstract void set_companion(AltosCompanion companion); + +	public AltosDataListener() { +	} + +	public AltosDataListener(AltosCalData cal_data) { +		this.cal_data = cal_data; +	} +} diff --git a/altoslib/AltosStateUpdate.java b/altoslib/AltosDataProvider.java index e9698cba..9589a8e6 100644 --- a/altoslib/AltosStateUpdate.java +++ b/altoslib/AltosDataProvider.java @@ -16,8 +16,8 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; -public interface AltosStateUpdate { -	public void	update_state(AltosState state) throws InterruptedException, AltosUnknownProduct; +public interface AltosDataProvider { +	public void	provide_data(AltosDataListener listener) throws InterruptedException, AltosUnknownProduct;  } diff --git a/altoslib/AltosDebug.java b/altoslib/AltosDebug.java index aa1b298f..24a25933 100644 --- a/altoslib/AltosDebug.java +++ b/altoslib/AltosDebug.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java index 0239c5ce..38efbf1a 100644 --- a/altoslib/AltosDistance.java +++ b/altoslib/AltosDistance.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosDistance extends AltosUnits { @@ -96,7 +96,7 @@ public class AltosDistance extends AltosUnits {  				}  			}; -		range_imperial[1] = new AltosUnitsRange(AltosConvert.feet_to_meters(1000), +		range_imperial[1] = new AltosUnitsRange(AltosConvert.feet_to_meters(5280),  							"mi", "miles") {  				double value(double v) {  					return AltosConvert.meters_to_miles(v); diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java index 6ed14d3a..ad7bf881 100644 --- a/altoslib/AltosEeprom.java +++ b/altoslib/AltosEeprom.java @@ -1,132 +1,291 @@  /* - * Copyright © 2013 Keith Packard <keithp@keithp.com> + * Copyright © 2017 Keith Packard <keithp@keithp.com>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * 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.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; -import java.io.*;  import java.util.*; -import java.text.*; +import java.io.*; + +public class AltosEeprom { -public abstract class AltosEeprom implements AltosStateUpdate { -	public int	cmd; -	public int	tick; -	public int	data8[]; -	public boolean	valid; +	private AltosJson	config; +	ArrayList<Byte>		data; +	private AltosConfigData	config_data; -	public int data8(int i) { -		return data8[i]; +	/* +	 * Public accessor APIs +	 */ +	public int data8(int offset) { +		return ((int) data.get(offset)) & 0xff;  	} -	public int data16(int i) { -		return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; +	public int data16(int offset) { +		return data8(offset) | (data8(offset+1) << 8);  	} -	public int data24(int i) { -		return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16); +	public int data24(int offset) { +		return (data8(offset) | +			(data8(offset+1) << 8) | +			(data8(offset+2) << 16));  	} -	public int data32(int i) { -		return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); +	public int data32(int offset) { +		return (data8(offset) | +			(data8(offset+1) << 8) | +			(data8(offset+2) << 16) | +			(data8(offset+3) << 24));  	} -	public boolean has_seconds() { return false; } +	public int size() { +		return data.size(); +	} -	public int seconds() { return 0; } +	public AltosConfigData config_data() { +		if (config_data == null) { +			config_data = (AltosConfigData) config.make(AltosConfigData.class); +			if (config_data == null) +				config_data = new AltosConfigData(); -	public final static int header_length = 4; +			if (config_data.log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN) { +				config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; +				if (config_data.product != null) { +					if (config_data.product.startsWith("TeleMetrum")) +						config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; +					else if (config_data.product.startsWith("TeleMini")) +						config_data.log_format = AltosLib.AO_LOG_FORMAT_TINY; +				} +			} +		} +		return config_data; +	} + +	private void write_config(Writer w) throws IOException { +		config.write(w, 0, true); +		w.append('\n'); +	} + +	/* +	 * Private I/O APIs +	 */ +	private void write_data(Writer w) throws IOException { +		PrintWriter pw = new PrintWriter(w); -	public abstract int record_length(); +		for (int i = 0; i < data.size(); i++) { +			if (i > 0) { +				if ((i & 0x1f) == 0) +					pw.printf("\n"); +				else +					pw.printf(" "); +			} +			pw.printf("%02x", data.get(i)); +		} +		w.append('\n'); +	} -	public void update_state(AltosState state) { -		if (cmd == AltosLib.AO_LOG_FLIGHT) -			state.set_boost_tick(tick); -		else -			state.set_tick(tick); +	private boolean read_config(InputStream stream) throws IOException { +		config = AltosJson.fromInputStream(stream); +		if (config == null) +			return false; +		return true;  	} -	public void write(PrintStream out) { -		out.printf("%c %04x", cmd, tick); -		if (data8 != null) { -			for (int i = 0; i < data8.length; i++) -				out.printf (" %02x", data8[i]); +	private String read_line(InputStream stream) throws IOException { +		StringBuffer	buffer = null; +		int		c; + +		for (;;) { +			c = stream.read(); +			if (c == -1 && buffer == null) +				return null; +			if (buffer == null) +				buffer = new StringBuffer(); +			if (c == -1 || c == '\n') +				return buffer.toString(); +			buffer.append((char) c);  		} -		out.printf ("\n");  	} -	public String string() { -		String	s; +	private boolean read_data(InputStream stream) throws IOException { +		String			s; + +		data = new ArrayList<Byte>(); +		while ((s = read_line(stream)) != null) { -		s = String.format("%c %04x", cmd, tick); -		if (data8 != null) { -			for (int i = 0; i < data8.length; i++) { -				String	d = String.format(" %02x", data8[i]); -				s = s.concat(d); +			String[] tokens = s.split("\\s+"); + +			for (int i = 0; i < tokens.length; i++) { +				if (tokens[i].length() > 0) { +					try { +						data.add((byte) AltosLib.fromhex(tokens[i])); +					} catch (NumberFormatException e) { +						throw new IOException(e.toString()); +					} +				}  			}  		} -		s = s.concat("\n"); -		return s; +		return true;  	} -	void parse_chunk(AltosEepromChunk chunk, int start) throws ParseException { -		cmd = chunk.data(start); +	private boolean read_old_config(InputStream stream) throws IOException { +		AltosConfigData	cfg = new AltosConfigData(); +		for (;;) { +			boolean	done = false; -		int data_length = record_length() - header_length; +			/* The data starts with an upper case F character followed by a space */ +			stream.mark(2); +			int	first = stream.read(); +			if (first == 'F') { +				int second =  stream.read(); +				if (second == ' ') +					done = true; +			} +			stream.reset(); +			if (done) +				break; -		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; +			String line = read_line(stream); +			if (line == null) +				return false; +			cfg.parse_line(line);  		} +		config = new AltosJson(cfg); +		return true; +	} -		tick = chunk.data16(start+2); +	private boolean read_old_data(InputStream stream) throws IOException { +		String line; -		data8 = new int[data_length]; -		for (int i = 0; i < data_length; i++) -			data8[i] = chunk.data(start + header_length + i); -	} +		data = new ArrayList<Byte>(); +		while ((line = read_line(stream)) != null) { +			String[] tokens = line.split("\\s+"); -	void parse_string(String line) { -		valid = false; -		tick = 0; -		cmd = AltosLib.AO_LOG_INVALID; +			/* Make sure there's at least a type and time */ +			if (tokens.length < 2) +				break; -		int data_length = record_length() - header_length; +			/* packet type */ +			if (tokens[0].length() != 1) +				break; +			int start = data.size(); -		if (line == null) -			return; -		try { -			String[] tokens = line.split("\\s+"); +			if (config_data().log_format != AltosLib.AO_LOG_FORMAT_TINY) { +				byte cmd = (byte) tokens[0].codePointAt(0); +				data.add(cmd); -			if (tokens[0].length() == 1) { -				if (tokens.length == 2 + data_length) { -					cmd = tokens[0].codePointAt(0); -					tick = Integer.parseInt(tokens[1],16); -					valid = true; -					data8 = new int[data_length]; +				int time = AltosLib.fromhex(tokens[1]); -					for (int i = 0; i < data_length; i++) -						data8[i] = Integer.parseInt(tokens[2 + i],16); +				data.add((byte) 0); +				data.add((byte) (time & 0xff)); +				data.add((byte) (time >> 8)); +			} +			if (tokens.length == 4) { +				/* Handle ancient log files */ +				if (config_data().log_format == AltosLib.AO_LOG_FORMAT_TINY) { +					/* +					 * Ancient TeleMini log files stored "extra" data to pretend +					 * that it was a TeleMetrum device. Throw that away and +					 * just save the actual log data. +					 */ +					int a = AltosLib.fromhex(tokens[2]); +					int b = AltosLib.fromhex(tokens[3]); +					if (a != 0) +						b = 0x8000 | a; +					data.add((byte) (b & 0xff)); +					data.add((byte) ((b >> 8))); +				} else { +					for (int i = 2; i < tokens.length; i++) { +						int v = AltosLib.fromhex(tokens[i]); +						data.add((byte) (v & 0xff)); +						data.add((byte) ((v >> 8))); +					} +					/* Re-compute the checksum byte */ +					data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start)));  				} +			} else { +				for (int i = 2; i < tokens.length; i++) +					data.add((byte) AltosLib.fromhex(tokens[i])); +				/* Re-compute the checksum byte */ +				data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start)));  			} -		} catch (NumberFormatException ne) {  		} +		return true; +	} + +	private void read(InputStream stream) throws IOException { +		BufferedInputStream	bis = new BufferedInputStream(stream); + +		bis.mark(1); +		int c = bis.read(); +		bis.reset(); + +		if (c == '{') { +			if (!read_config(bis)) +				throw new IOException("failed to read config"); +			if (!read_data(bis)) +				throw new IOException("failed to read data"); +		} else { +			if (!read_old_config(bis)) +				throw new IOException("failed to read old config"); +			if (!read_old_data(bis)) +				throw new IOException("failed to read old data"); +		} +	} + +	/* +	 * Public APIs for I/O +	 */ +	public void write(Writer w) throws IOException { +		write_config(w); +		write_data(w); +	} + +	public String toString() { +		try { +			Writer	w = new StringWriter(); + +			write(w); +			return w.toString(); +		} catch (Exception e) { +			return null; +		} +	} + +	public void print() throws IOException { +		System.out.printf("%s", toString()); +	} + +	/* +	 * Constructors +	 */ +	public AltosEeprom(InputStream stream) throws IOException { +		read(stream); +	} + +	public AltosEeprom(String s) throws IOException { +		read(new AltosStringInputStream(s)); +	} + +	public AltosEeprom(AltosJson config, ArrayList<Byte> data) { +		this.config = config; +		this.data = data; +	} + +	public AltosEeprom(AltosConfigData config_data, ArrayList<Byte> data) { +		this.config = new AltosJson(config_data); +		this.data = data; +	} + +	public AltosEeprom() {  	}  } diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java index 32d9f8ea..4f12c190 100644 --- a/altoslib/AltosEepromChunk.java +++ b/altoslib/AltosEepromChunk.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*;  import java.util.concurrent.*; @@ -63,40 +63,8 @@ public class AltosEepromChunk {  		return true;  	} -	public AltosEeprom eeprom(int offset, int log_format, AltosState state) throws ParseException { -		AltosEeprom	eeprom = null; -		switch (log_format) { -		case AltosLib.AO_LOG_FORMAT_FULL: -			eeprom = new AltosEepromTM(this, offset); -			break; -		case AltosLib.AO_LOG_FORMAT_TINY: -			eeprom = new AltosEepromTMini(this, offset, state); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEMETRY: -		case AltosLib.AO_LOG_FORMAT_TELESCIENCE: -			break; -		case AltosLib.AO_LOG_FORMAT_TELEMEGA: -		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: -			eeprom = new AltosEepromMega(this, offset, log_format); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEMETRUM: -			eeprom = new AltosEepromMetrum2(this, offset); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEMINI2: -		case AltosLib.AO_LOG_FORMAT_TELEMINI3: -		case AltosLib.AO_LOG_FORMAT_EASYMINI: -			eeprom = new AltosEepromMini(this, offset); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEGPS: -			eeprom = new AltosEepromGPS(this, offset); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEFIRETWO: -			eeprom = new AltosEepromFireTwo(this, offset); -			break; -		default: -			throw new ParseException("unknown eeprom format " + log_format, 0); -		} -		return eeprom; +	public boolean erased() { +		return erased(0, chunk_size);  	}  	public AltosEepromChunk(AltosLink link, int block, boolean flush) diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java index c38fcfdf..33f0dd17 100644 --- a/altoslib/AltosEepromDownload.java +++ b/altoslib/AltosEepromDownload.java @@ -16,13 +16,60 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*;  import java.text.*;  import java.util.concurrent.*; +class AltosEepromNameData extends AltosDataListener { +	AltosGPS	gps = null; + +	public void set_rssi(int rssi, int status) { } +	public void set_received_time(long received_time) { } + +	public void set_acceleration(double accel) { } +	public void set_pressure(double pa) { } +	public void set_thrust(double N) { } + +	public void set_temperature(double deg_c) { } +	public void set_battery_voltage(double volts) { } + +	public void set_apogee_voltage(double volts) { } +	public void set_main_voltage(double volts) { } + +	public void set_gps(AltosGPS gps) { +		if (gps != null && +		    gps.year != AltosLib.MISSING && +		    gps.month != AltosLib.MISSING && +		    gps.day != AltosLib.MISSING) { +			this.gps = gps; +		} +	} + +	public boolean done() { +		if (gps == null) +			return false; +		return true; +	} + +	public void set_gyro(double roll, double pitch, double yaw) { } +	public void set_accel_ground(double along, double across, double through) { } +	public void set_accel(double along, double across, double through) { } +	public void set_mag(double along, double across, double through) { } +	public void set_pyro_voltage(double volts) { } +	public void set_igniter_voltage(double[] voltage) { } +	public void set_pyro_fired(int pyro_mask) { } +	public void set_companion(AltosCompanion companion) { } +	public void set_kalman(double height, double speed, double acceleration) { } +	public void set_orient(double new_orient) { } + +	public AltosEepromNameData(AltosCalData cal_data) { +		super(cal_data); +	} +} +  public class AltosEepromDownload implements Runnable {  	AltosLink		link; @@ -30,65 +77,38 @@ public class AltosEepromDownload implements Runnable {  	Thread			eeprom_thread;  	AltosEepromMonitor	monitor; -	boolean			want_file; -	FileWriter		eeprom_file; -	LinkedList<String>	eeprom_pending; -  	AltosEepromList		flights; -	boolean			success;  	String			parse_errors; -	AltosState		state; -	private void FlushPending() throws IOException { -		for (String s : flights.config_data) { -			eeprom_file.write(s); -			eeprom_file.write('\n'); -		} +	private boolean has_gps_date(AltosState state) { +		if (state == null) +			return false; -		for (String s : eeprom_pending) -			eeprom_file.write(s); +		AltosGPS gps = state.gps; + +		return gps != null && +			gps.year != AltosLib.MISSING && +			gps.month != AltosLib.MISSING && +			gps.day != AltosLib.MISSING;  	} -	private void CheckFile(boolean force) throws IOException { -		if (eeprom_file != null) -			return; -		if (force || (state.flight != 0 && want_file)) { -			AltosFile		eeprom_name; -			AltosGPS		gps = state.gps; - -			if (gps != null && -			    gps.year != AltosLib.MISSING && -			    gps.month != AltosLib.MISSING && -			    gps.day != AltosLib.MISSING) -			{ -				eeprom_name = new AltosFile(gps.year, gps.month, gps.day, -							    state.serial, state.flight, "eeprom"); -			} else -				eeprom_name = new AltosFile(state.serial, state.flight, "eeprom"); - -			eeprom_file = new FileWriter(eeprom_name); -			if (eeprom_file != null) { -				monitor.set_filename(eeprom_name.getName()); -				FlushPending(); -				eeprom_pending = null; -			} -		} +	private AltosFile MakeFile(int serial, int flight, AltosEepromNameData name_data) throws IOException { +		AltosFile		eeprom_name; + +		if (name_data.gps != null) { +			AltosGPS		gps = name_data.gps; +			eeprom_name = new AltosFile(gps.year, gps.month, gps.day, +						    serial, flight, "eeprom"); +		} else +			eeprom_name = new AltosFile(serial, flight, "eeprom"); + +		return eeprom_name;  	}  	boolean			done;  	int			prev_state;  	int			state_block; -	void LogEeprom(AltosEeprom r) throws IOException { -		if (r.cmd != AltosLib.AO_LOG_INVALID) { -			String line = r.string(); -			if (eeprom_file != null) -				eeprom_file.write(line); -			else -				eeprom_pending.add(line); -		} -	} -  	void LogError(String error) {  		if (parse_errors != null)  			parse_errors.concat(error.concat("\n")); @@ -96,112 +116,100 @@ public class AltosEepromDownload implements Runnable {  			parse_errors = error;  	} -	void CaptureEeprom(AltosEepromChunk eechunk, int log_format) throws IOException, ParseException { -		boolean any_valid = false; -		boolean got_flight = false; - -		int record_length = 8; - -		state.set_serial(flights.config_data.serial); -		monitor.set_serial(flights.config_data.serial); - -		for (int i = 0; i < AltosEepromChunk.chunk_size && !done; i += record_length) { -			AltosEeprom r = null; - -			try { -				r = eechunk.eeprom(i, log_format, state); -			} catch (ParseException pe) { -				LogError(pe.getMessage()); -				r = null; -			} +	class BlockCache extends Hashtable<Integer,AltosEepromChunk> { +		AltosEepromLog	log; -			if (r == null) -				continue; - -			record_length = r.record_length(); - -			r.update_state(state); +		AltosEepromChunk get(int start, boolean add) throws TimeoutException, InterruptedException { +			if (contains(start)) +				return super.get(start); +			AltosEepromChunk eechunk = new AltosEepromChunk(link, start, start == log.start_block); +			if (add) +				put(start, eechunk); +			return eechunk; +		} -			if (!got_flight && state.flight != AltosLib.MISSING) -				monitor.set_flight(state.flight); +		public BlockCache(AltosEepromLog log) { +			this.log = log; +		} +	} -			/* Monitor state transitions to update display */ -			if (state.state() != AltosLib.ao_flight_invalid && -			    state.state() <= AltosLib.ao_flight_landed) -			{ -				if (state.state() > AltosLib.ao_flight_pad) -					want_file = true; -				if (state.state() == AltosLib.ao_flight_landed) -					done = true; -			} +	int FindLastLog(AltosEepromLog log, BlockCache cache) throws TimeoutException, InterruptedException { +		int	low = log.start_block; +		int	high = log.end_block - 1; -			if (state.gps != null) -				want_file = true; +		while (low <= high) { +			int mid = (high + low) / 2; -			if (r.valid) { -				any_valid = true; -				LogEeprom(r); -			} +			if (!cache.get(mid, true).erased()) +				low = mid + 1; +			else +				high = mid - 1;  		} -		if (!any_valid) -			done = true; - -		CheckFile(false); +		return low;  	}  	void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException, ParseException {  		int			block, state_block = 0;  		int			log_format = flights.config_data.log_format; - -		state = new AltosState(); +		BlockCache		cache = new BlockCache(log);  		done = false;  		if (flights.config_data.serial < 0)  			throw new IOException("no serial number found"); -		/* Reset per-capture variables */ -		want_file = false; -		eeprom_pending = new LinkedList<String>(); -  		/* Set serial number in the monitor dialog window */ -		/* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ - -		state_block = log.start_block; -		prev_state = AltosLib.ao_flight_startup; -		for (block = log.start_block; !done && block < log.end_block; block++) { -			AltosEepromChunk	eechunk = new AltosEepromChunk(link, block, block == log.start_block); - -			/* -			 * Guess what kind of data is there if the device -			 * didn't tell us -			 */ - -			if (log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN) { -				if (block == log.start_block) { -					if (eechunk.data(0) == AltosLib.AO_LOG_FLIGHT) -						log_format = AltosLib.AO_LOG_FORMAT_FULL; -					else -						log_format = AltosLib.AO_LOG_FORMAT_TINY; -				} -			} +		monitor.set_serial(log.serial); +		monitor.set_flight(log.flight); -			CaptureEeprom (eechunk, log_format); +		int	start_block = log.start_block; +		int	end_block = FindLastLog(log, cache); -			if (state.state() != prev_state && state.state() != AltosLib.ao_flight_invalid) { -				state_block = block; -				prev_state = state.state(); -			} +		monitor.set_max(end_block - start_block - 1); -			monitor.set_value(state.state_name(), -					  state.state(), -					  block - state_block, -					  block - log.start_block); +		ArrayList<Byte> data = new ArrayList<Byte>(); + +		/* Now scan the eeprom, reading blocks of data to create a byte array of data */ + +		for (block = start_block; block < end_block; block++) { +			monitor.set_block(block - start_block); + +			AltosEepromChunk	eechunk = cache.get(block, false); + +			for (int i = 0; i < eechunk.data.length; i++) +				data.add((byte) eechunk.data[i]);  		} -		CheckFile(true); + +		/* Construct our internal representation of the eeprom data */ +		AltosEeprom	eeprom = new AltosEeprom(flights.config_data, data); + +		/* Now see if we can't actually parse the resulting +		 * file to generate a better filename. Note that this +		 * doesn't need to work; we'll still save the data using +		 * a less accurate name. +		 */ +		AltosEepromRecordSet		set = new AltosEepromRecordSet(eeprom); +		AltosEepromNameData name_data = new AltosEepromNameData(set.cal_data()); + +		for (AltosEepromRecord record : set.ordered) { +			record.provide_data(name_data, set.cal_data()); +			if (name_data.done()) +				break; +		} + +		AltosFile f = MakeFile(flights.config_data.serial, log.flight, name_data); + +		monitor.set_filename(f.toString()); + +		FileWriter w = new FileWriter(f); + +		eeprom.write(w); +		w.close();  	}  	public void run () { +		boolean success = false; +  		try {  			boolean	failed = false;  			if (remote) @@ -211,16 +219,11 @@ public class AltosEepromDownload implements Runnable {  				parse_errors = null;  				if (log.selected) {  					monitor.reset(); -					eeprom_file = null;  					try {  						CaptureLog(log);  					} catch (ParseException e) {  						LogError(e.getMessage());  					} -					if (eeprom_file != null) { -						eeprom_file.flush(); -						eeprom_file.close(); -					}  				}  				if (parse_errors != null) {  					failed = true; @@ -273,12 +276,6 @@ public class AltosEepromDownload implements Runnable {  		link = given_link;  		remote = given_remote;  		flights = given_flights; -		success = false; - -		if (flights.config_data.log_has_state()) -			monitor.set_states(AltosLib.ao_flight_boost, AltosLib.ao_flight_landed); -		else -			monitor.set_states(AltosLib.ao_flight_invalid, AltosLib.ao_flight_invalid);  		monitor.start();  	} diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index 5544ec37..067f0302 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -16,127 +16,36 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*;  import java.text.*; -class AltosEepromIterator implements Iterator<AltosState> { -	AltosState		state; -	Iterator<AltosEeprom>	body; -	AltosEeprom		next; -	boolean			seen; +public class AltosEepromFile implements AltosRecordSet { -	public boolean hasNext() { -		return !seen || body.hasNext(); -	} - -	public AltosState next() { -		if (seen) { -			AltosState	n = state.clone(); -			AltosEeprom	e = body.next(); - -			e.update_state(n); -			state = n; -		} -		seen = true; -		return state; -	} - -	public void remove () { -	} - -	public AltosEepromIterator(AltosState start, Iterator<AltosEeprom> body) { -		this.state = start; -		this.body = body; -		this.seen = false; -	} -} - -public class AltosEepromFile extends AltosStateIterable { - -	AltosEepromIterable	headers; -	AltosEepromIterable	body; -	AltosState		start; +	AltosEepromRecordSet	set;  	public void write_comments(PrintStream out) { -		headers.write(out);  	}  	public void write(PrintStream out) { -		headers.write(out); -		body.write(out); +		out.printf("%s\n", set.eeprom.toString());  	} -	public AltosEepromFile(FileInputStream input) { -		headers = new AltosEepromIterable(AltosEepromHeader.read(input)); - -		start = headers.state(); -		if (start.state() != AltosLib.ao_flight_stateless) -			start.set_state(AltosLib.ao_flight_pad); - -		if (start.log_format == AltosLib.MISSING) { -			if (start.product != null) { -				if (start.product.startsWith("TeleMetrum")) -					start.log_format = AltosLib.AO_LOG_FORMAT_FULL; -				else if (start.product.startsWith("TeleMini")) -					start.log_format = AltosLib.AO_LOG_FORMAT_TINY; -			} -		} - -		switch (start.log_format) { -		case AltosLib.AO_LOG_FORMAT_FULL: -			body = new AltosEepromIterable(AltosEepromTM.read(input)); -			break; -		case AltosLib.AO_LOG_FORMAT_TINY: -			body = new AltosEepromIterable(AltosEepromTMini.read(input)); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEMETRY: -		case AltosLib.AO_LOG_FORMAT_TELESCIENCE: -		case AltosLib.AO_LOG_FORMAT_TELEMEGA: -		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: -			body = new AltosEepromIterable(AltosEepromMega.read(input, start.log_format)); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEMETRUM: -			body = new AltosEepromIterable(AltosEepromMetrum2.read(input)); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEMINI2: -		case AltosLib.AO_LOG_FORMAT_TELEMINI3: -		case AltosLib.AO_LOG_FORMAT_EASYMINI: -			body = new AltosEepromIterable(AltosEepromMini.read(input)); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEGPS: -			body = new AltosEepromIterable(AltosEepromGPS.read(input)); -			break; -		case AltosLib.AO_LOG_FORMAT_TELEFIRETWO: -			body = new AltosEepromIterable(AltosEepromFireTwo.read(input)); -			break; -		default: -			body = new AltosEepromIterable(new LinkedList<AltosEeprom>()); -			break; -		} +	public AltosEepromFile(InputStream input) throws IOException { +		set = new AltosEepromRecordSet(input); +	} -		/* Find boost tick */ -		AltosState	state = start.clone(); -		for (AltosEeprom eeprom : body) { -			eeprom.update_state(state); -			state.finish_update(); -			if (state.state() >= AltosLib.ao_flight_boost) { -				start.set_boost_tick(state.tick); -				break; -			} -		} +	public AltosConfigData config_data() { +		return set.config_data();  	} -	public Iterator<AltosState> iterator() { -		AltosState		state = start.clone(); -		Iterator<AltosEeprom>	i = body.iterator(); +	public AltosCalData cal_data() { +		return set.cal_data(); +	} -		while (i.hasNext() && !state.valid()) { -			i.next().update_state(state); -			state.finish_update(); -		} -		return new AltosEepromIterator(state, i); +	public void capture_series(AltosDataListener series) { +		set.capture_series(series);  	}  } diff --git a/altoslib/AltosEepromHeader.java b/altoslib/AltosEepromHeader.java deleted file mode 100644 index 37b666b4..00000000 --- a/altoslib/AltosEepromHeader.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright © 2013 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altoslib_11; - -import java.io.*; -import java.util.*; -import java.text.*; - -public class AltosEepromHeader extends AltosEeprom { - -	public int	cmd; -	public String	data; -	public int	config_a, config_b, config_c; -	public boolean	last; -	public boolean	valid; - -	public int record_length () { return 0; } - -	/* XXX pull rest of config data to state */ -	public void update_state(AltosState state) { -		switch (cmd) { -		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.set_callsign(data); -			break; -		case AltosLib.AO_LOG_ACCEL_CAL: -			state.set_accel_g(config_a, config_b); -			break; -		case AltosLib.AO_LOG_RADIO_CAL: -			break; -		case AltosLib.AO_LOG_MANUFACTURER: -			break; -		case AltosLib.AO_LOG_PRODUCT: -			state.product = data; -			break; -		case AltosLib.AO_LOG_LOG_FORMAT: -			state.set_log_format(config_a); -			break; -		case AltosLib.AO_LOG_SERIAL_NUMBER: -			state.set_serial(config_a); -			break; -		case AltosLib.AO_LOG_BARO_RESERVED: -			state.make_baro(); -			state.baro.reserved = config_a; -			break; -		case AltosLib.AO_LOG_BARO_SENS: -			state.make_baro(); -			state.baro.sens = config_a; -			break; -		case AltosLib.AO_LOG_BARO_OFF: -			state.make_baro(); -			state.baro.off = config_a; -			break; -		case AltosLib.AO_LOG_BARO_TCS: -			state.make_baro(); -			state.baro.tcs = config_a; -			break; -		case AltosLib.AO_LOG_BARO_TCO: -			state.make_baro(); -			state.baro.tco = config_a; -			break; -		case AltosLib.AO_LOG_BARO_TREF: -			state.make_baro(); -			state.baro.tref = config_a; -			break; -		case AltosLib.AO_LOG_BARO_TEMPSENS: -			state.make_baro(); -			state.baro.tempsens = config_a; -			break; -		case AltosLib.AO_LOG_BARO_CRC: -			state.make_baro(); -			state.baro.crc = config_a; -			break; -		case AltosLib.AO_LOG_IMU_CAL: -			state.set_accel_zero(config_a, config_b, config_c); -			break; -		case AltosLib.AO_LOG_SOFTWARE_VERSION: -			state.set_firmware_version(data); -			break; -		case AltosLib.AO_LOG_FREQUENCY: -		case AltosLib.AO_LOG_APOGEE_LOCKOUT: -		case AltosLib.AO_LOG_RADIO_RATE: -		case AltosLib.AO_LOG_IGNITE_MODE: -			break; -		case AltosLib.AO_LOG_PAD_ORIENTATION: -			state.set_pad_orientation(config_a); -			break; -		case AltosLib.AO_LOG_RADIO_ENABLE: -		case AltosLib.AO_LOG_AES_KEY: -		case AltosLib.AO_LOG_APRS: -		case AltosLib.AO_LOG_BEEP_SETTING: -		case AltosLib.AO_LOG_TRACKER_SETTING: -		case AltosLib.AO_LOG_PYRO_TIME: -		case AltosLib.AO_LOG_APRS_ID: -			break; -		case AltosLib.AO_LOG_ALTITUDE_32: -			state.set_altitude_32(config_a); -			break; -		} -	} - -	public void write(PrintStream out) { -		switch (cmd) { -		case AltosLib.AO_LOG_CONFIG_VERSION: -			out.printf("# Config version: %s\n", data); -			break; -		case AltosLib.AO_LOG_MAIN_DEPLOY: -			out.printf("# Main deploy: %s\n", config_a); -			break; -		case AltosLib.AO_LOG_APOGEE_DELAY: -			out.printf("# Apogee delay: %s\n", config_a); -			break; -		case AltosLib.AO_LOG_RADIO_CHANNEL: -			out.printf("# Radio channel: %s\n", config_a); -			break; -		case AltosLib.AO_LOG_CALLSIGN: -			out.printf("# Callsign: %s\n", data); -			break; -		case AltosLib.AO_LOG_ACCEL_CAL: -			out.printf ("# Accel cal: %d %d\n", config_a, config_b); -			break; -		case AltosLib.AO_LOG_RADIO_CAL: -			out.printf ("# Radio cal: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_MAX_FLIGHT_LOG: -			out.printf ("# Max flight log: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_MANUFACTURER: -			out.printf ("# Manufacturer: %s\n", data); -			break; -		case AltosLib.AO_LOG_PRODUCT: -			out.printf ("# Product: %s\n", data); -			break; -		case AltosLib.AO_LOG_SERIAL_NUMBER: -			out.printf ("# Serial number: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_SOFTWARE_VERSION: -			out.printf ("# Software version: %s\n", data); -			break; -		case AltosLib.AO_LOG_BARO_RESERVED: -			out.printf ("# Baro reserved: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_BARO_SENS: -			out.printf ("# Baro sens: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_BARO_OFF: -			out.printf ("# Baro off: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_BARO_TCS: -			out.printf ("# Baro tcs: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_BARO_TCO: -			out.printf ("# Baro tco: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_BARO_TREF: -			out.printf ("# Baro tref: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_BARO_TEMPSENS: -			out.printf ("# Baro tempsens: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_BARO_CRC: -			out.printf ("# Baro crc: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_IMU_CAL: -			out.printf ("# IMU cal: %d %d %d\n", config_a, config_b, config_c); -			break; -		case AltosLib.AO_LOG_FREQUENCY: -		case AltosLib.AO_LOG_APOGEE_LOCKOUT: -		case AltosLib.AO_LOG_RADIO_RATE: -		case AltosLib.AO_LOG_IGNITE_MODE: -			break; -		case AltosLib.AO_LOG_PAD_ORIENTATION: -			out.printf("# Pad orientation: %d\n", config_a); -			break; -		case AltosLib.AO_LOG_RADIO_ENABLE: -		case AltosLib.AO_LOG_AES_KEY: -		case AltosLib.AO_LOG_APRS: -		case AltosLib.AO_LOG_BEEP_SETTING: -		case AltosLib.AO_LOG_TRACKER_SETTING: -		case AltosLib.AO_LOG_PYRO_TIME: -		case AltosLib.AO_LOG_APRS_ID: -			break; -		case AltosLib.AO_LOG_ALTITUDE_32: -			out.printf("# Altitude-32: %d\n", config_a); -			break; -		} -	} - -	public AltosEepromHeader (String[] tokens) { -		last = false; -		valid = true; -		try { -			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; -				config_a = Integer.parseInt(tokens[2]); -			} else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) { -				cmd = AltosLib.AO_LOG_APOGEE_DELAY; -				config_a = Integer.parseInt(tokens[2]); -			} else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) { -				cmd = AltosLib.AO_LOG_RADIO_CHANNEL; -				config_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; -				config_a = Integer.parseInt(tokens[3]); -				config_b = Integer.parseInt(tokens[5]); -			} else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) { -				cmd = AltosLib.AO_LOG_RADIO_CAL; -				config_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; -				config_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; -				config_a = Integer.parseInt(tokens[1]); -			} else if (tokens[0].equals("log-format")) { -				cmd = AltosLib.AO_LOG_LOG_FORMAT; -				config_a = Integer.parseInt(tokens[1]); -			} else if (tokens[0].equals("altitude-32")) { -				cmd = AltosLib.AO_LOG_ALTITUDE_32; -				config_a = Integer.parseInt(tokens[1]); -			} else if (tokens[0].equals("software-version")) { -				cmd = AltosLib.AO_LOG_SOFTWARE_VERSION; -				data = tokens[1]; -				last = true; -			} else if (tokens[0].equals("ms5607")) { -				if (tokens[1].equals("reserved:")) { -					cmd = AltosLib.AO_LOG_BARO_RESERVED; -					config_a = Integer.parseInt(tokens[2]); -				} else if (tokens[1].equals("sens:")) { -					cmd = AltosLib.AO_LOG_BARO_SENS; -					config_a = Integer.parseInt(tokens[2]); -				} else if (tokens[1].equals("off:")) { -					cmd = AltosLib.AO_LOG_BARO_OFF; -					config_a = Integer.parseInt(tokens[2]); -				} else if (tokens[1].equals("tcs:")) { -					cmd = AltosLib.AO_LOG_BARO_TCS; -					config_a = Integer.parseInt(tokens[2]); -				} else if (tokens[1].equals("tco:")) { -					cmd = AltosLib.AO_LOG_BARO_TCO; -					config_a = Integer.parseInt(tokens[2]); -				} else if (tokens[1].equals("tref:")) { -					cmd = AltosLib.AO_LOG_BARO_TREF; -					config_a = Integer.parseInt(tokens[2]); -				} else if (tokens[1].equals("tempsens:")) { -					cmd = AltosLib.AO_LOG_BARO_TEMPSENS; -					config_a = Integer.parseInt(tokens[2]); -				} else if (tokens[1].equals("crc:")) { -					cmd = AltosLib.AO_LOG_BARO_CRC; -					config_a = Integer.parseInt(tokens[2]); -				} else { -					cmd = AltosLib.AO_LOG_INVALID; -					data = tokens[2]; -				} -			} else if (tokens[0].equals("IMU") && tokens[1].equals("cal")) { -				cmd = AltosLib.AO_LOG_IMU_CAL; -				config_a = Integer.parseInt(tokens[3]); -				config_b = Integer.parseInt(tokens[5]); -				config_c = Integer.parseInt(tokens[7]); -			} else if (tokens[0].equals("Pad") && tokens[1].equals("orientation:")) { -				cmd = AltosLib.AO_LOG_PAD_ORIENTATION; -				config_a = Integer.parseInt(tokens[2]); -			} else -				valid = false; -		} catch (Exception e) { -			valid = false; -		} -	} - -	static public LinkedList<AltosEeprom> read(FileInputStream input) { -		LinkedList<AltosEeprom> headers = new LinkedList<AltosEeprom>(); - -		for (;;) { -			try { -				String line = AltosLib.gets(input); -				if (line == null) -					break; -				AltosEepromHeader header = new AltosEepromHeader(line); -				headers.add(header); -				if (header.last) -					break; -			} catch (IOException ie) { -				break; -			} -		} - -		return headers; -	} - -	static public void write (PrintStream out, LinkedList<AltosEepromHeader> headers) { -		out.printf("# Comments\n"); -		for (AltosEepromHeader header : headers) { -			header.write(out); -		} - -	} - -	public AltosEepromHeader (String line) { -		this(line.split("\\s+")); -	} -} diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java deleted file mode 100644 index 77632ac1..00000000 --- a/altoslib/AltosEepromIterable.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright © 2013 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altoslib_11; - -import java.io.*; -import java.util.*; -import java.text.*; - -class AltosEepromOrdered implements Comparable<AltosEepromOrdered> { -	AltosEeprom	eeprom; -	int		index; -	int		tick; - -	int cmdi() { -		if (eeprom.cmd == AltosLib.AO_LOG_FLIGHT) -			return 0; -		return 1; -	} - -	public int compareTo(AltosEepromOrdered o) { -		int	cmd_diff = cmdi() - o.cmdi(); - -		if (cmd_diff != 0) -			return cmd_diff; - -		if (eeprom.has_seconds() && o.eeprom.has_seconds()) { -			int	seconds_diff = eeprom.seconds() - o.eeprom.seconds(); - -			if (seconds_diff != 0) -				return seconds_diff; -		} - -		int	tick_diff = tick - o.tick; - -		if (tick_diff != 0) -			return tick_diff; -		return index - o.index; -	} - -	AltosEepromOrdered (AltosEeprom eeprom, int index, int tick) { -		this.eeprom = eeprom; -		this.index = index; -		this.tick = tick; -	} -} - -class AltosEepromOrderedIterator implements Iterator<AltosEeprom> { -	TreeSet<AltosEepromOrdered>	olist; -	Iterator<AltosEepromOrdered>	oiterator; - -	public AltosEepromOrderedIterator(Iterable<AltosEeprom> eeproms) { -		olist = new TreeSet<AltosEepromOrdered>(); - -		int	tick = 0; -		int	index = 0; -		boolean	first = true; - -		for (AltosEeprom e : eeproms) { -			int	t = e.tick; -			if (first) -				tick = t; -			else { -				while (t < tick - 32767) -					t += 65536; -				tick = t; -			} -			olist.add(new AltosEepromOrdered(e, index++, tick)); -			first = false; -		} - -		oiterator = olist.iterator(); -	} - -	public boolean hasNext() { -		return oiterator.hasNext(); -	} - -	public AltosEeprom next() { -		return oiterator.next().eeprom; -	} - -	public void remove () { -	} -} - -public class AltosEepromIterable implements Iterable<AltosEeprom> { -	public LinkedList<AltosEeprom> eeproms; - -	public void write(PrintStream out) { -		for (AltosEeprom eeprom : eeproms) -			eeprom.write(out); -	} - -	public AltosState state() { -		AltosState	state = new AltosState(); - -		for (AltosEeprom header : eeproms) -			header.update_state(state); -		return state; -	} - -	public AltosEepromIterable(LinkedList<AltosEeprom> eeproms) { -		this.eeproms = eeproms; -	} - -	public Iterator<AltosEeprom> iterator() { -		if (eeproms == null) -			eeproms = new LinkedList<AltosEeprom>(); -		return new AltosEepromOrderedIterator(eeproms); -	} -} diff --git a/altoslib/AltosEepromList.java b/altoslib/AltosEepromList.java index fc72fd95..55d47e20 100644 --- a/altoslib/AltosEepromList.java +++ b/altoslib/AltosEepromList.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; diff --git a/altoslib/AltosEepromLog.java b/altoslib/AltosEepromLog.java index 1bca6563..8d1f3fc4 100644 --- a/altoslib/AltosEepromLog.java +++ b/altoslib/AltosEepromLog.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*;  import java.util.concurrent.*; @@ -32,8 +32,6 @@ public class AltosEepromLog {  	public int		start_block;  	public int		end_block; -	public int		year, month, day; -  	public boolean		selected;  	public AltosEepromLog(AltosConfigData config_data, @@ -43,7 +41,6 @@ public class AltosEepromLog {  		throws InterruptedException, TimeoutException {  		int		block; -		boolean		has_date = false;  		flight = in_flight;  		if (flight != 0) @@ -56,43 +53,5 @@ public class AltosEepromLog {  		 * 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 < AltosEepromChunk.chunk_size; i += AltosEepromTM.record_length) { -					try { -						AltosEepromTM r = new AltosEepromTM(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/AltosEepromMega.java b/altoslib/AltosEepromMega.java deleted file mode 100644 index 082d6054..00000000 --- a/altoslib/AltosEepromMega.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright © 2011 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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. - */ - -package org.altusmetrum.altoslib_11; - -import java.io.*; -import java.util.*; -import java.text.*; - -public class AltosEepromMega extends AltosEeprom { -	public static final int	record_length = 32; - -	public static final int max_sat = 12; - -	private int log_format; - -	public int record_length() { return record_length; } - -	/* 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_accel_along() { return data16(8); } -	public int ground_accel_across() { return data16(10); } -	public int ground_accel_through() { return data16(12); } -	public int ground_roll() { -		switch (log_format) { -		case AltosLib.AO_LOG_FORMAT_TELEMEGA: -			return data32(16); -		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: -			return data16(14); -		default: -			return AltosLib.MISSING; -		} -	} -	public int ground_pitch() { -		switch (log_format) { -		case AltosLib.AO_LOG_FORMAT_TELEMEGA: -			return data32(20); -		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: -			return data16(16); -		default: -			return AltosLib.MISSING; -		} -	} -	public int ground_yaw() { -		switch (log_format) { -		case AltosLib.AO_LOG_FORMAT_TELEMEGA: -			return data32(24); -		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: -			return data16(18); -		default: -			return AltosLib.MISSING; -		} -	} - -	/* 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() { return data16(26); } - -	/* AO_LOG_TEMP_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 int pyro() { return data16(26); } - -	/* AO_LOG_GPS_TIME elements */ -	public int latitude() { return data32(0); } -	public int longitude() { return data32(4); } -	public int altitude_low() { return data16(8); } -	public int hour() { return data8(10); } -	public int minute() { return data8(11); } -	public int second() { return data8(12); } -	public int flags() { return data8(13); } -	public int year() { return data8(14); } -	public int month() { return data8(15); } -	public int day() { return data8(16); } -	public int course() { return data8(17); } -	public int ground_speed() { return data16(18); } -	public int climb_rate() { return data16(20); } -	public int pdop() { return data8(22); } -	public int hdop() { return data8(23); } -	public int vdop() { return data8(24); } -	public int mode() { return data8(25); } -	public int altitude_high() { return data16(26); } - -	/* AO_LOG_GPS_SAT elements */ -	public int nsat() { return data16(0); } -	public int svid(int n) { return data8(2 + n * 2); } -	public int c_n(int n) { return data8(2 + n * 2 + 1); } - -	public AltosEepromMega (AltosEepromChunk chunk, int start, int log_format) throws ParseException { -		this.log_format = log_format; -		parse_chunk(chunk, start); -	} - -	public void update_state(AltosState state) { -		super.update_state(state); - -		AltosGPS	gps; - -		/* Flush any pending GPS changes */ -		if (state.gps_pending) { -			switch (cmd) { -			case AltosLib.AO_LOG_GPS_LAT: -			case AltosLib.AO_LOG_GPS_LON: -			case AltosLib.AO_LOG_GPS_ALT: -			case AltosLib.AO_LOG_GPS_SAT: -			case AltosLib.AO_LOG_GPS_DATE: -				break; -			default: -				state.set_temp_gps(); -				break; -			} -		} - -		switch (cmd) { -		case AltosLib.AO_LOG_FLIGHT: -			state.set_boost_tick(tick); -			state.set_flight(flight()); -			state.set_ground_accel(ground_accel()); -			state.set_ground_pressure(ground_pres()); -			state.set_accel_ground(ground_accel_along(), -					       ground_accel_across(), -					       ground_accel_through()); -			state.set_gyro_zero(ground_roll() / 512.0, -					    ground_pitch() / 512.0, -					    ground_yaw() / 512.0); -			break; -		case AltosLib.AO_LOG_STATE: -			state.set_tick(tick); -			state.set_state(state()); -			break; -		case AltosLib.AO_LOG_SENSOR: -			state.set_tick(tick); -			state.set_ms5607(pres(), temp()); - -			AltosIMU	imu = new AltosIMU(accel_y(),	/* along */ -							   accel_x(),	/* across */ -							   accel_z(),	/* through */ -							   gyro_y(),	/* roll */ -							   gyro_x(),	/* pitch */ -							   gyro_z());	/* yaw */ - -			if (log_format == AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD) -				state.check_imu_wrap(imu); - -			state.set_imu(imu); - -			state.set_mag(new AltosMag(mag_x(), -						   mag_y(), -						   mag_z())); - -			state.set_accel(accel()); - -			break; -		case AltosLib.AO_LOG_TEMP_VOLT: -			state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); -			state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt())); - -			int nsense = nsense(); - -			state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2))); -			state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1))); - -			double voltages[] = new double[nsense-2]; -			for (int i = 0; i < nsense-2; i++) -				voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); - -			state.set_ignitor_voltage(voltages); -			state.set_pyro_fired(pyro()); -			break; -		case AltosLib.AO_LOG_GPS_TIME: -			state.set_tick(tick); -			gps = state.make_temp_gps(false); -			gps.lat = latitude() / 1e7; -			gps.lon = longitude() / 1e7; - -			if (state.altitude_32()) -				gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16); -			else -				gps.alt = altitude_low(); - -			gps.hour = hour(); -			gps.minute = minute(); -			gps.second = second(); - -			int flags = flags(); - -			gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; -			gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; -			gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> -				AltosLib.AO_GPS_NUM_SAT_SHIFT; - -			gps.year = 2000 + year(); -			gps.month = month(); -			gps.day = day(); -			gps.ground_speed = ground_speed() * 1.0e-2; -			gps.course = course() * 2; -			gps.climb_rate = climb_rate() * 1.0e-2; -			if (state.compare_version("1.4.9") >= 0) { -				gps.pdop = pdop() / 10.0; -				gps.hdop = hdop() / 10.0; -				gps.vdop = vdop() / 10.0; -			} else { -				gps.pdop = pdop() / 100.0; -				if (gps.pdop < 0.8) -					gps.pdop += 2.56; -				gps.hdop = hdop() / 100.0; -				if (gps.hdop < 0.8) -					gps.hdop += 2.56; -				gps.vdop = vdop() / 100.0; -				if (gps.vdop < 0.8) -					gps.vdop += 2.56; -			} -			break; -		case AltosLib.AO_LOG_GPS_SAT: -			state.set_tick(tick); -			gps = state.make_temp_gps(true); - -			int n = nsat(); -			if (n > max_sat) -				n = max_sat; -			for (int i = 0; i < n; i++) -				gps.add_sat(svid(i), c_n(i)); -			break; -		} -	} - -	public AltosEepromMega (String line, int log_format) { -		this.log_format = log_format; -		parse_string(line); -	} - -	static public LinkedList<AltosEeprom> read(FileInputStream input, int log_format) { -		LinkedList<AltosEeprom> megas = new LinkedList<AltosEeprom>(); - -		for (;;) { -			try { -				String line = AltosLib.gets(input); -				if (line == null) -					break; -				try { -					AltosEepromMega mega = new AltosEepromMega(line, log_format); -					if (mega.cmd != AltosLib.AO_LOG_INVALID) -						megas.add(mega); -				} catch (Exception e) { -					System.out.printf ("exception\n"); -				} -			} catch (IOException ie) { -				break; -			} -		} - -		return megas; -	} -} diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java deleted file mode 100644 index 04155071..00000000 --- a/altoslib/AltosEepromMini.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright © 2011 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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. - */ - -package org.altusmetrum.altoslib_11; - -import java.io.*; -import java.util.*; -import java.text.*; - -public class AltosEepromMini extends AltosEeprom { -	public static final int	record_length = 16; - -	public int record_length() { return record_length; } - -	/* AO_LOG_FLIGHT elements */ -	public int flight() { return data16(0); } -	public int ground_pres() { return data32(4); } - -	/* AO_LOG_STATE elements */ -	public int state() { return data16(0); } -	public int reason() { return data16(2); } - -	/* AO_LOG_SENSOR elements */ -	public int pres() { return data24(0); } -	public int temp() { return data24(3); } -	public int sense_a() { return data16(6); } -	public int sense_m() { return data16(8); } -	public int v_batt() { return data16(10); } - -	private double battery_voltage(AltosState state, int sensor) { -		if (state.log_format == AltosLib.AO_LOG_FORMAT_EASYMINI) -			return AltosConvert.easy_mini_voltage(sensor, state.serial); -		if (state.log_format == AltosLib.AO_LOG_FORMAT_TELEMINI2) -			return AltosConvert.tele_mini_2_voltage(sensor); -		if (state.log_format == AltosLib.AO_LOG_FORMAT_TELEMINI3) -			return AltosConvert.tele_mini_3_battery_voltage(sensor); -		return -1; -	} - -	private double pyro_voltage(AltosState state, int sensor) { -		if (state.log_format == AltosLib.AO_LOG_FORMAT_EASYMINI) -			return AltosConvert.easy_mini_voltage(sensor, state.serial); -		if (state.log_format == AltosLib.AO_LOG_FORMAT_TELEMINI2) -			return AltosConvert.tele_mini_2_voltage(sensor); -		if (state.log_format == AltosLib.AO_LOG_FORMAT_TELEMINI3) -			return AltosConvert.tele_mini_3_pyro_voltage(sensor); -		return -1; -	} - -	public void update_state(AltosState state) { -		super.update_state(state); - -		switch (cmd) { -		case AltosLib.AO_LOG_FLIGHT: -			state.set_flight(flight()); -			state.set_ground_pressure(ground_pres()); -			break; -		case AltosLib.AO_LOG_STATE: -			state.set_state(state()); -			break; -		case AltosLib.AO_LOG_SENSOR: -			state.set_ms5607(pres(), temp()); -			state.set_apogee_voltage(pyro_voltage(state, sense_a())); -			state.set_main_voltage(pyro_voltage(state, sense_m())); -			state.set_battery_voltage(battery_voltage(state, v_batt())); -			break; -		} -	} - -	public AltosEepromMini (AltosEepromChunk chunk, int start) throws ParseException { -		parse_chunk(chunk, start); -	} - -	public AltosEepromMini (String line) { -		parse_string(line); -	} - -	public AltosEepromMini(int in_cmd, int in_tick) { -		cmd = in_cmd; -		tick = in_tick; -		valid = true; -	} - -	static public LinkedList<AltosEeprom> read(FileInputStream input) { -		LinkedList<AltosEeprom> minis = new LinkedList<AltosEeprom>(); - -		for (;;) { -			try { -				String line = AltosLib.gets(input); -				if (line == null) -					break; -				AltosEepromMini mini = new AltosEepromMini(line); -				minis.add(mini); -			} catch (IOException ie) { -				break; -			} -		} - -		return minis; -	} -} diff --git a/altoslib/AltosEepromMonitor.java b/altoslib/AltosEepromMonitor.java index 792fde27..a99ec687 100644 --- a/altoslib/AltosEepromMonitor.java +++ b/altoslib/AltosEepromMonitor.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosEepromMonitor { -	public void set_states(int min_state, int max_state); +	public void set_block(int in_block); -	public void set_value(String in_state_name, int in_state, int in_state_block, int in_block); +	public void set_max(int in_max);  	public void set_serial(int in_serial); diff --git a/altoslib/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java new file mode 100644 index 00000000..094584fe --- /dev/null +++ b/altoslib/AltosEepromRecord.java @@ -0,0 +1,126 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public abstract class AltosEepromRecord implements Comparable<AltosEepromRecord> { + +	AltosEeprom		eeprom; + +	int			wide_tick; + +	final int		start; +	final int		length; + +	public final static int header_length = 4; + +	public int cmd() { +		return eeprom.data8(start); +	} + +	public int tick() { +		return eeprom.data16(start+2); +	} + +	public int data8(int i) { +		i += start + header_length; +		return eeprom.data8(i); +	} + +	public int data16(int i) { +		return ((data8(i) | (data8(i+1) << 8)) << 16) >> 16; +	} + +	public int data24(int i) { +		return data8(i) | (data8(i+1) << 8) | (data8(i+2) << 16); +	} + +	public int data32(int i) { +		return data8(i) | (data8(i+1) << 8) | (data8(i+2) << 16) | (data8(i+3) << 24); +	} + +	public boolean valid(int s) { +		return AltosConvert.checksum(eeprom.data, s, length) == 0; +	} + +	public boolean valid() { +		return valid(start); +	} + +	private int cmdi() { +		if (cmd() == AltosLib.AO_LOG_FLIGHT) +			return 0; +		return 1; +	} + +	public AltosConfigData config_data() { +		return eeprom.config_data(); +	} + +	public int compareTo(AltosEepromRecord o) { +		int	cmd_diff = cmdi() - o.cmdi(); + +		if (cmd_diff != 0) +			return cmd_diff; + +		int	tick_diff = wide_tick - o.wide_tick; + +		if (tick_diff != 0) +			return tick_diff; +		return start - o.start; +	} + +	/* AltosDataProvider */ +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		cal_data.set_tick(tick()); +		if (cmd() == AltosLib.AO_LOG_FLIGHT) +			cal_data.set_boost_tick(); +		listener.set_time(cal_data.time()); + +		/* Flush any pending GPS changes */ +		if (!AltosLib.is_gps_cmd(cmd())) { +			AltosGPS gps = cal_data.temp_gps(); +			if (gps != null) { +				listener.set_gps(gps); +				cal_data.reset_temp_gps(); +			} +		} +	} + +	public int next_start() { +		int	s = start + length; + +		while (s + length <= eeprom.data.size()) { +			if (valid(s)) +				return s; +			s += length; +		} +		return -1; +	} + +	public boolean hasNext() { +		return next_start() >= 0; +	} + +	public abstract AltosEepromRecord next(); + +	public AltosEepromRecord(AltosEeprom eeprom, int start, int length) { +		this.eeprom = eeprom; +		this.start = start; +		this.length = length; + +		while (start + length < eeprom.data.size() && !valid()) +			start += length; +	} +} diff --git a/altoslib/AltosEepromFireTwo.java b/altoslib/AltosEepromRecordFireTwo.java index dd510280..d6b74d1b 100644 --- a/altoslib/AltosEepromFireTwo.java +++ b/altoslib/AltosEepromRecordFireTwo.java @@ -16,21 +16,17 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*;  import java.text.*; -public class AltosEepromFireTwo extends AltosEeprom { +public class AltosEepromRecordFireTwo extends AltosEepromRecord {  	public static final int	record_length = 32; -	public int record_length() { return record_length; } -  	/* AO_LOG_FLIGHT elements */  	public int flight() { return data16(0); } -	public int idle_pres() { return data16(2); } -	public int idle_thrust() { return data16(4); }  	/* AO_LOG_STATE elements */  	public int state() { return data16(0); } @@ -41,21 +37,15 @@ public class AltosEepromFireTwo extends AltosEeprom {  	public int thrust() { return data16(2); }  	public int temp(int i) { return data16(4+i*2); } -	public AltosEepromFireTwo (AltosEepromChunk chunk, int start) throws ParseException { -		parse_chunk(chunk, start); -	} -  	private static final double r_above = 5600.0;  	private static final double r_below = 10000.0;  	private static final double v_adc = 3.3; -	private static double -	firetwo_adc(int raw) { +	private static double firetwo_adc(int raw) {  		return raw / 4095.0;  	} -	private static double -	adc_to_pa(int adc) { +	public static double adc_to_pa(int adc) {  		/* raw adc to processor voltage, then back through the  		 * voltage divider to the sensor voltage @@ -67,52 +57,46 @@ public class AltosEepromFireTwo extends AltosEeprom {  		if (v < 0.5) v = 0.5;  		if (v > 4.5) v = 4.5; -		double	psi = (v - 0.5) / 4.0 * 1600.0; +		double	psi = (v - 0.5) / 4.0 * 2500.0;  		return AltosConvert.psi_to_pa(psi);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public static double adc_to_n(int adc) { +		double v = firetwo_adc(adc); + +		/* this is a total guess */ +		return AltosConvert.lb_to_n(v * 298 * 9.807); +	} + +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); -		switch (cmd) { +		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			state.set_flight(flight()); -			state.set_ground_pressure(adc_to_pa(idle_pres())); +			cal_data.set_flight(flight());  			break;  		case AltosLib.AO_LOG_STATE: -			state.set_state(state()); +			listener.set_state(state());  			break;  		case AltosLib.AO_LOG_SENSOR: -			state.set_pressure(adc_to_pa(pres())); +			listener.set_pressure(adc_to_pa(pres())); +			listener.set_thrust(adc_to_n(thrust()));  			break;  		}  	} -	public AltosEepromFireTwo (String line) { -		parse_string(line); +	public AltosEepromRecord next() { +		int	s = next_start(); +		if (s < 0) +			return null; +		return new AltosEepromRecordFireTwo(eeprom, s);  	} -	static public LinkedList<AltosEeprom> read(FileInputStream input) { -		LinkedList<AltosEeprom> firetwos = new LinkedList<AltosEeprom>(); - -		for (;;) { -			try { -				String line = AltosLib.gets(input); -				if (line == null) -					break; -				try { -					AltosEepromFireTwo firetwo = new AltosEepromFireTwo(line); - -					if (firetwo.cmd != AltosLib.AO_LOG_INVALID) -						firetwos.add(firetwo); -				} catch (Exception e) { -					System.out.printf ("exception\n"); -				} -			} catch (IOException ie) { -				break; -			} -		} +	public AltosEepromRecordFireTwo(AltosEeprom eeprom, int start) { +		super(eeprom, start, record_length); +	} -		return firetwos; +	public AltosEepromRecordFireTwo(AltosEeprom eeprom) { +		this(eeprom, 0);  	}  } diff --git a/altoslib/AltosEepromRecordFull.java b/altoslib/AltosEepromRecordFull.java new file mode 100644 index 00000000..85709f73 --- /dev/null +++ b/altoslib/AltosEepromRecordFull.java @@ -0,0 +1,114 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosEepromRecordFull extends AltosEepromRecord { +	public static final int	record_length = 8; + +	public static final int max_sat = 12; + +	public static final int two_g_default = 16294 - 15758; + +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + +		super.provide_data(listener, cal_data); +		AltosGPS	gps; + +		switch (cmd()) { +		case AltosLib.AO_LOG_FLIGHT: +			listener.set_state(AltosLib.ao_flight_pad); +			cal_data.set_ground_accel(data16(0)); +			cal_data.set_flight(data16(2)); +			if (cal_data.accel_plus_g == AltosLib.MISSING) +				cal_data.set_accel_plus_minus(data16(0), data16(0) + two_g_default); +			break; +		case AltosLib.AO_LOG_SENSOR: +			listener.set_acceleration(cal_data.acceleration(data16(0))); +			listener.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); +			break; +		case AltosLib.AO_LOG_PRESSURE: +			listener.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); +			break; +		case AltosLib.AO_LOG_TEMP_VOLT: +			listener.set_temperature(AltosConvert.thermometer_to_temperature(data16(0))); +			listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(data16(2))); +			break; +		case AltosLib.AO_LOG_DEPLOY: +			listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(data16(0))); +			listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(data16(2))); +			break; +		case AltosLib.AO_LOG_STATE: +			listener.set_state(data16(0)); +			break; +		case AltosLib.AO_LOG_GPS_TIME: +			gps = cal_data.make_temp_gps(tick(),false); + +			gps.hour = data8(0); +			gps.minute = data8(1); +			gps.second = data8(2); + +			int flags = data8(3); + +			gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; +			gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; +			gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> +				AltosLib.AO_GPS_NUM_SAT_SHIFT; +			break; +		case AltosLib.AO_LOG_GPS_LAT: +			gps = cal_data.make_temp_gps(tick(),false); + +			int lat32 = data32(0); +			gps.lat = (double) lat32 / 1e7; +			break; +		case AltosLib.AO_LOG_GPS_LON: +			gps = cal_data.make_temp_gps(tick(),false); + +			int lon32 = data32(0); +			gps.lon = (double) lon32 / 1e7; +			break; +		case AltosLib.AO_LOG_GPS_ALT: +			gps = cal_data.make_temp_gps(tick(),false); +			gps.alt = data16(0); +			break; +		case AltosLib.AO_LOG_GPS_SAT: +			gps = cal_data.make_temp_gps(tick(),true); +			int svid = data16(0); +			int c_n0 = data16(3); +			gps.add_sat(svid, c_n0); +			break; +		case AltosLib.AO_LOG_GPS_DATE: +			gps = cal_data.make_temp_gps(tick(),false); +			gps.year = data8(0) + 2000; +			gps.month = data8(1); +			gps.day = data8(2); +			break; +		} +	} + +	public AltosEepromRecord next() { +		int	s = next_start(); +		if (s < 0) +			return null; +		return new AltosEepromRecordFull(eeprom, s); +	} + +	public AltosEepromRecordFull(AltosEeprom eeprom, int start) { +		super(eeprom, start, record_length); +	} + +	public AltosEepromRecordFull(AltosEeprom eeprom) { +		this(eeprom, 0); +	} +} diff --git a/altoslib/AltosEepromGPS.java b/altoslib/AltosEepromRecordGps.java index e76b36dd..5cf5db39 100644 --- a/altoslib/AltosEepromGPS.java +++ b/altoslib/AltosEepromRecordGps.java @@ -1,5 +1,5 @@  /* - * Copyright © 2014 Keith Packard <keithp@keithp.com> + * Copyright © 2017 Keith Packard <keithp@keithp.com>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -16,19 +16,15 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*;  import java.text.*; -public class AltosEepromGPS extends AltosEeprom { +public class AltosEepromRecordGps extends AltosEepromRecord {  	public static final int	record_length = 32; -	public static final int max_sat = 12; - -	public int record_length() { return record_length; } -  	/* AO_LOG_FLIGHT elements */  	public int flight() { return data16(0); }  	public int start_altitude() { return data16(2); } @@ -55,10 +51,8 @@ public class AltosEepromGPS extends AltosEeprom {  	public int mode() { return data8(25); }  	public int altitude_high() { return data16(26); } -	public boolean has_seconds() { return cmd == AltosLib.AO_LOG_GPS_TIME; } - -	public int seconds() { -		switch (cmd) { +	private int seconds() { +		switch (cmd()) {  		case AltosLib.AO_LOG_GPS_TIME:  			return second() + 60 * (minute() + 60 * (hour() + 24 * (day() + 31 * month())));  		default: @@ -66,44 +60,33 @@ public class AltosEepromGPS extends AltosEeprom {  		}  	} -	public AltosEepromGPS (AltosEepromChunk chunk, int start) throws ParseException { -		parse_chunk(chunk, start); +	public int compareTo(AltosEepromRecord o) { +		AltosEepromRecordGps og = (AltosEepromRecordGps) o; + +		int	seconds_diff = seconds() - og.seconds(); + +		if (seconds_diff != 0) +			return seconds_diff; + +		return start - o.start;  	} -	public void update_state(AltosState state) { -		super.update_state(state); - -		AltosGPS	gps; - -		/* Flush any pending GPS changes */ -		if (state.gps_pending) { -			switch (cmd) { -			case AltosLib.AO_LOG_GPS_LAT: -			case AltosLib.AO_LOG_GPS_LON: -			case AltosLib.AO_LOG_GPS_ALT: -			case AltosLib.AO_LOG_GPS_SAT: -			case AltosLib.AO_LOG_GPS_DATE: -				break; -			default: -				state.set_temp_gps(); -				break; -			} -		} +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); -		switch (cmd) { +		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			if (state.flight == AltosLib.MISSING) { -				state.set_boost_tick(tick); -				state.set_flight(flight()); +			if (cal_data.flight == AltosLib.MISSING) { +				cal_data.set_boost_tick(); +				cal_data.set_flight(flight());  			}  			/* no place to log start lat/lon yet */  			break;  		case AltosLib.AO_LOG_GPS_TIME: -			state.set_tick(tick); -			gps = state.make_temp_gps(false); +			AltosGPS gps = new AltosGPS();  			gps.lat = latitude() / 1e7;  			gps.lon = longitude() / 1e7; -			if (state.altitude_32()) +			if (eeprom.config_data().altitude_32 == 1)  				gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);  			else  				gps.alt = altitude_low(); @@ -125,7 +108,7 @@ public class AltosEepromGPS extends AltosEeprom {  			gps.ground_speed = ground_speed() * 1.0e-2;  			gps.course = course() * 2;  			gps.climb_rate = climb_rate() * 1.0e-2; -			if (state.compare_version("1.4.9") >= 0) { +			if (eeprom.config_data().compare_version("1.4.9") >= 0) {  				gps.pdop = pdop() / 10.0;  				gps.hdop = hdop() / 10.0;  				gps.vdop = vdop() / 10.0; @@ -140,34 +123,23 @@ public class AltosEepromGPS extends AltosEeprom {  				if (gps.vdop < 0.8)  					gps.vdop += 2.56;  			} +			listener.set_gps(gps);  			break;  		}  	} -	public AltosEepromGPS (String line) { -		parse_string(line); +	public AltosEepromRecord next() { +		int	s = next_start(); +		if (s < 0) +			return null; +		return new AltosEepromRecordGps(eeprom, s);  	} -	static public LinkedList<AltosEeprom> read(FileInputStream input) { -		LinkedList<AltosEeprom> tgpss = new LinkedList<AltosEeprom>(); - -		for (;;) { -			try { -				String line = AltosLib.gets(input); -				if (line == null) -					break; -				try { -					AltosEepromGPS tgps = new AltosEepromGPS(line); -					if (tgps.cmd != AltosLib.AO_LOG_INVALID) -						tgpss.add(tgps); -				} catch (Exception e) { -					System.out.printf ("exception\n"); -				} -			} catch (IOException ie) { -				break; -			} -		} +	public AltosEepromRecordGps(AltosEeprom eeprom, int start) { +		super(eeprom, start, record_length); +	} -		return tgpss; +	public AltosEepromRecordGps(AltosEeprom eeprom) { +		this(eeprom, 0);  	}  } diff --git a/altoslib/AltosEepromRecordMega.java b/altoslib/AltosEepromRecordMega.java new file mode 100644 index 00000000..ad3e23fd --- /dev/null +++ b/altoslib/AltosEepromRecordMega.java @@ -0,0 +1,260 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosEepromRecordMega extends AltosEepromRecord { +	public static final int	record_length = 32; + +	public static final int max_sat = 12; + +	private int log_format; + +	/* AO_LOG_FLIGHT elements */ +	private int flight() { return data16(0); } +	private int ground_accel() { return data16(2); } +	private int ground_pres() { return data32(4); } +	private int ground_accel_along() { return data16(8); } +	private int ground_accel_across() { return data16(10); } +	private int ground_accel_through() { return data16(12); } +	private int ground_roll() { +		switch (log_format) { +		case AltosLib.AO_LOG_FORMAT_TELEMEGA: +			return data32(16); +		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: +			return data16(14); +		default: +			return AltosLib.MISSING; +		} +	} +	private int ground_pitch() { +		switch (log_format) { +		case AltosLib.AO_LOG_FORMAT_TELEMEGA: +			return data32(20); +		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: +			return data16(16); +		default: +			return AltosLib.MISSING; +		} +	} +	private int ground_yaw() { +		switch (log_format) { +		case AltosLib.AO_LOG_FORMAT_TELEMEGA: +			return data32(24); +		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: +			return data16(18); +		default: +			return AltosLib.MISSING; +		} +	} + +	/* AO_LOG_STATE elements */ +	private int state() { return data16(0); } +	private int reason() { return data16(2); } + +	/* AO_LOG_SENSOR elements */ +	private int pres() { return data32(0); } +	private int temp() { return data32(4); } +	private int accel_x() { return data16(8); } +	private int accel_y() { return data16(10); } +	private int accel_z() { return data16(12); } +	private int gyro_x() { return data16(14); } +	private int gyro_y() { return data16(16); } +	private int gyro_z() { return data16(18); } +	private int mag_x() { return data16(20); } +	private int mag_z() { return data16(22); } +	private int mag_y() { return data16(24); } +	private int accel() { return data16(26); } + +	/* AO_LOG_TEMP_VOLT elements */ +	private int v_batt() { return data16(0); } +	private int v_pbatt() { return data16(2); } +	private int nsense() { return data16(4); } +	private int sense(int i) { return data16(6 + i * 2); } +	private int pyro() { return data16(26); } + +	/* AO_LOG_GPS_TIME elements */ +	private int latitude() { return data32(0); } +	private int longitude() { return data32(4); } +	private int altitude_low() { return data16(8); } +	private int hour() { return data8(10); } +	private int minute() { return data8(11); } +	private int second() { return data8(12); } +	private int flags() { return data8(13); } +	private int year() { return data8(14); } +	private int month() { return data8(15); } +	private int day() { return data8(16); } +	private int course() { return data8(17); } +	private int ground_speed() { return data16(18); } +	private int climb_rate() { return data16(20); } +	private int pdop() { return data8(22); } +	private int hdop() { return data8(23); } +	private int vdop() { return data8(24); } +	private int mode() { return data8(25); } +	private int altitude_high() { return data16(26); } + +	/* AO_LOG_GPS_SAT elements */ +	private int nsat() { return data16(0); } +	private int svid(int n) { return data8(2 + n * 2); } +	private int c_n(int n) { return data8(2 + n * 2 + 1); } + +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); + +		AltosGPS	gps; + +		switch (cmd()) { +		case AltosLib.AO_LOG_FLIGHT: +			cal_data.set_flight(flight()); +			cal_data.set_ground_accel(ground_accel()); +			cal_data.set_ground_pressure(ground_pres()); +			listener.set_accel_ground(ground_accel_along(), +						  ground_accel_across(), +						  ground_accel_through()); +			cal_data.set_gyro_zero(ground_roll() / 512.0, +					       ground_pitch() / 512.0, +					       ground_yaw() / 512.0); +			break; +		case AltosLib.AO_LOG_STATE: +			listener.set_state(state()); +			break; +		case AltosLib.AO_LOG_SENSOR: +			AltosConfigData config_data = eeprom.config_data(); +			AltosPresTemp pt = config_data.ms5607().pres_temp(pres(), temp());; +			listener.set_pressure(pt.pres); +			listener.set_temperature(pt.temp); + +			int	accel_along = accel_y(); +			int	accel_across = accel_x(); +			int	accel_through = accel_z(); +			int	gyro_roll = gyro_y(); +			int	gyro_pitch = gyro_x(); +			int	gyro_yaw = gyro_z(); + +			int	mag_along = mag_y(); +			int	mag_across = mag_x(); +			int	mag_through = mag_z(); + +			if (log_format == AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD) +				cal_data.check_imu_wrap(gyro_roll, gyro_pitch, gyro_yaw); + +			listener.set_accel(cal_data.accel_along(accel_along), +					   cal_data.accel_across(accel_across), +					   cal_data.accel_through(accel_through)); +			listener.set_gyro(cal_data.gyro_roll(gyro_roll), +					  cal_data.gyro_pitch(gyro_pitch), +					  cal_data.gyro_yaw(gyro_yaw)); + +			listener.set_mag(cal_data.mag_along(mag_along), +					 cal_data.mag_across(mag_across), +					 cal_data.mag_through(mag_through)); + + +			final double lsb_per_g = 1920.0/105.5; + +			double acceleration = AltosConvert.acceleration_from_sensor( +				accel(), +				cal_data.ground_accel, +				cal_data.ground_accel + 2 * lsb_per_g, +				cal_data.ground_accel); + +			listener.set_acceleration(acceleration); +			break; +		case AltosLib.AO_LOG_TEMP_VOLT: +			listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); +			listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt())); + +			int nsense = nsense(); + +			listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2))); +			listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1))); + +			double voltages[] = new double[nsense-2]; +			for (int i = 0; i < nsense-2; i++) +				voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); + +			listener.set_igniter_voltage(voltages); +			listener.set_pyro_fired(pyro()); +			break; +		case AltosLib.AO_LOG_GPS_TIME: +			gps = cal_data.make_temp_gps(tick(), false); +			gps.lat = latitude() / 1e7; +			gps.lon = longitude() / 1e7; + +			if (config_data().altitude_32()) +				gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16); +			else +				gps.alt = altitude_low(); + +			gps.hour = hour(); +			gps.minute = minute(); +			gps.second = second(); + +			int flags = flags(); + +			gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; +			gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; +			gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> +				AltosLib.AO_GPS_NUM_SAT_SHIFT; + +			gps.year = 2000 + year(); +			gps.month = month(); +			gps.day = day(); +			gps.ground_speed = ground_speed() * 1.0e-2; +			gps.course = course() * 2; +			gps.climb_rate = climb_rate() * 1.0e-2; +			if (config_data().compare_version("1.4.9") >= 0) { +				gps.pdop = pdop() / 10.0; +				gps.hdop = hdop() / 10.0; +				gps.vdop = vdop() / 10.0; +			} else { +				gps.pdop = pdop() / 100.0; +				if (gps.pdop < 0.8) +					gps.pdop += 2.56; +				gps.hdop = hdop() / 100.0; +				if (gps.hdop < 0.8) +					gps.hdop += 2.56; +				gps.vdop = vdop() / 100.0; +				if (gps.vdop < 0.8) +					gps.vdop += 2.56; +			} +			break; +		case AltosLib.AO_LOG_GPS_SAT: +			gps = cal_data.make_temp_gps(tick(), true); + +			int n = nsat(); +			if (n > max_sat) +				n = max_sat; +			for (int i = 0; i < n; i++) +				gps.add_sat(svid(i), c_n(i)); +			break; +		} +	} + +	public AltosEepromRecord next() { +		int	s = next_start(); +		if (s < 0) +			return null; +		return new AltosEepromRecordMega(eeprom, s); +	} + +	public AltosEepromRecordMega(AltosEeprom eeprom, int start) { +		super(eeprom, start, record_length); +		log_format = eeprom.config_data().log_format; +	} + +	public AltosEepromRecordMega(AltosEeprom eeprom) { +		this(eeprom, 0); +	} +} diff --git a/altoslib/AltosEepromMetrum2.java b/altoslib/AltosEepromRecordMetrum.java index f685b3ce..3da50544 100644 --- a/altoslib/AltosEepromMetrum2.java +++ b/altoslib/AltosEepromRecordMetrum.java @@ -1,5 +1,5 @@  /* - * Copyright © 2011 Keith Packard <keithp@keithp.com> + * Copyright © 2017 Keith Packard <keithp@keithp.com>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -16,13 +16,9 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; -import java.io.*; -import java.util.*; -import java.text.*; - -public class AltosEepromMetrum2 extends AltosEeprom { +public class AltosEepromRecordMetrum extends AltosEepromRecord {  	public static final int	record_length = 16;  	public int record_length() { return record_length; } @@ -69,64 +65,42 @@ public class AltosEepromMetrum2 extends AltosEeprom {  	public int svid(int n) { return data8(2 + n * 2); }  	public int c_n(int n) { return data8(2 + n * 2 + 1); } -	public AltosEepromMetrum2 (AltosEepromChunk chunk, int start) throws ParseException { -		parse_chunk(chunk, start); -	} - -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data);  		AltosGPS	gps; -		/* Flush any pending GPS changes */ -		if (state.gps_pending) { -			switch (cmd) { -			case AltosLib.AO_LOG_GPS_POS: -			case AltosLib.AO_LOG_GPS_LAT: -			case AltosLib.AO_LOG_GPS_LON: -			case AltosLib.AO_LOG_GPS_ALT: -			case AltosLib.AO_LOG_GPS_SAT: -			case AltosLib.AO_LOG_GPS_DATE: -				break; -			default: -				state.set_temp_gps(); -				break; -			} -		} - -		switch (cmd) { +		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			state.set_flight(flight()); -			state.set_ground_accel(ground_accel()); -			state.set_ground_pressure(ground_pres()); -//			state.set_temperature(ground_temp() / 100.0); +			cal_data.set_flight(flight()); +			cal_data.set_ground_accel(ground_accel()); +			cal_data.set_ground_pressure(ground_pres());  			break;  		case AltosLib.AO_LOG_STATE: -			state.set_state(state()); +			listener.set_state(state());  			break;  		case AltosLib.AO_LOG_SENSOR: -			state.set_ms5607(pres(), temp()); -			state.set_accel(accel()); - +			AltosPresTemp pt = eeprom.config_data().ms5607().pres_temp(pres(), temp()); +			listener.set_pressure(pt.pres); +			listener.set_temperature(pt.temp); +			listener.set_acceleration(cal_data.acceleration(accel()));  			break;  		case AltosLib.AO_LOG_TEMP_VOLT: -			state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); - -			state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); -			state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); - +			listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); +			listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); +			listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));  			break;  		case AltosLib.AO_LOG_GPS_POS: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(), false);  			gps.lat = latitude() / 1e7;  			gps.lon = longitude() / 1e7; -			if (state.altitude_32()) +			if (config_data().altitude_32())  				gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);  			else  				gps.alt = altitude_low();  			break;  		case AltosLib.AO_LOG_GPS_TIME: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(), false);  			gps.hour = hour();  			gps.minute = minute(); @@ -145,7 +119,7 @@ public class AltosEepromMetrum2 extends AltosEeprom {  			gps.pdop = pdop() / 10.0;  			break;  		case AltosLib.AO_LOG_GPS_SAT: -			gps = state.make_temp_gps(true); +			gps = cal_data.make_temp_gps(tick(), true);  			int n = nsat();  			for (int i = 0; i < n; i++) @@ -154,31 +128,18 @@ public class AltosEepromMetrum2 extends AltosEeprom {  		}  	} -	public AltosEepromMetrum2 (String line) { -		parse_string(line); +	public AltosEepromRecord next() { +		int	s = next_start(); +		if (s < 0) +			return null; +		return new AltosEepromRecordMetrum(eeprom, s);  	} -	static public LinkedList<AltosEeprom> read(FileInputStream input) { -		LinkedList<AltosEeprom> metrums = new LinkedList<AltosEeprom>(); - -		for (;;) { -			try { -				String line = AltosLib.gets(input); -				if (line == null) -					break; -				try { -					AltosEepromMetrum2 metrum = new AltosEepromMetrum2(line); - -					if (metrum.cmd != AltosLib.AO_LOG_INVALID) -						metrums.add(metrum); -				} catch (Exception e) { -					System.out.printf ("exception\n"); -				} -			} catch (IOException ie) { -				break; -			} -		} +	public AltosEepromRecordMetrum(AltosEeprom eeprom, int start) { +		super(eeprom, start, record_length); +	} -		return metrums; +	public AltosEepromRecordMetrum(AltosEeprom eeprom) { +		this(eeprom, 0);  	}  } diff --git a/altoslib/AltosEepromRecordMini.java b/altoslib/AltosEepromRecordMini.java new file mode 100644 index 00000000..55696693 --- /dev/null +++ b/altoslib/AltosEepromRecordMini.java @@ -0,0 +1,105 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosEepromRecordMini extends AltosEepromRecord { +	public static final int	record_length = 16; + +	/* AO_LOG_FLIGHT elements */ +	public int flight() { return data16(0); } +	public int ground_pres() { return data32(4); } + +	/* AO_LOG_STATE elements */ +	public int state() { return data16(0); } +	public int reason() { return data16(2); } + +	/* AO_LOG_SENSOR elements */ +	public int pres() { return data24(0); } +	public int temp() { return data24(3); } +	public int sense_a() { return data16(6); } +	public int sense_m() { return data16(8); } +	public int v_batt() { return data16(10); } + +	private int log_format() { +		return eeprom.config_data().log_format; +	} + +	private double battery_voltage(int sensor) { +		int log_format = log_format(); +		if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI1) +			return AltosConvert.easy_mini_1_voltage(sensor, eeprom.config_data().serial); +		if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI2) +			return AltosConvert.easy_mini_2_voltage(sensor); +		if (log_format == AltosLib.AO_LOG_FORMAT_TELEMINI2) +			return AltosConvert.tele_mini_2_voltage(sensor); +		if (log_format == AltosLib.AO_LOG_FORMAT_TELEMINI3) +			return AltosConvert.tele_mini_3_battery_voltage(sensor); +		return -1; +	} + +	private double pyro_voltage(int sensor) { +		int log_format = log_format(); +		if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI1) +			return AltosConvert.easy_mini_1_voltage(sensor, eeprom.config_data().serial); +		if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI2) +			return AltosConvert.easy_mini_2_voltage(sensor); +		if (log_format == AltosLib.AO_LOG_FORMAT_TELEMINI2) +			return AltosConvert.tele_mini_2_voltage(sensor); +		if (log_format == AltosLib.AO_LOG_FORMAT_TELEMINI3) +			return AltosConvert.tele_mini_3_pyro_voltage(sensor); +		return -1; +	} + +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); + +		switch (cmd()) { +		case AltosLib.AO_LOG_FLIGHT: +			cal_data.set_flight(flight()); +			cal_data.set_ground_pressure(ground_pres()); +			break; +		case AltosLib.AO_LOG_STATE: +			listener.set_state(state()); +			break; +		case AltosLib.AO_LOG_SENSOR: +			AltosPresTemp pt = eeprom.config_data().ms5607().pres_temp(pres(), temp()); +			listener.set_pressure(pt.pres); +			listener.set_temperature(pt.temp); +			listener.set_apogee_voltage(pyro_voltage(sense_a())); +			listener.set_main_voltage(pyro_voltage(sense_m())); +			listener.set_battery_voltage(battery_voltage(v_batt())); +			break; +		} +	} + +	public AltosEepromRecord next() { +		int	s = next_start(); +		if (s < 0) +			return null; +		return new AltosEepromRecordMini(eeprom, s); +	} + +	public AltosEepromRecordMini(AltosEeprom eeprom, int start) { +		super(eeprom, start, record_length); +	} + +	public AltosEepromRecordMini(AltosEeprom eeprom) { +		this(eeprom, 0); +	} +} diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java new file mode 100644 index 00000000..48e90c05 --- /dev/null +++ b/altoslib/AltosEepromRecordSet.java @@ -0,0 +1,120 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +import java.io.*; +import java.util.*; + +public class AltosEepromRecordSet implements AltosRecordSet { +	AltosEeprom			eeprom; +	TreeSet<AltosEepromRecord>	ordered; +	AltosCalData			cal_data; + +	public AltosConfigData config_data() { +		return eeprom.config_data(); +	} + +	public AltosCalData cal_data() { +		if (cal_data == null) { +			cal_data = new AltosCalData(config_data()); +			for (AltosEepromRecord record : ordered) { +				if (record.cmd() == AltosLib.AO_LOG_FLIGHT) { +					cal_data.set_tick(record.tick()); +					cal_data.set_boost_tick(); +					break; +				} +			} +		} +		return cal_data; +	} + +	public void capture_series(AltosDataListener listener) { +		AltosCalData	cal_data = cal_data(); + +		cal_data.reset(); +		for (AltosEepromRecord record : ordered) { +			record.provide_data(listener, cal_data); +		} +		listener.finish(); +	} + +	public AltosEepromRecordSet(AltosEeprom eeprom) { +		this.eeprom = eeprom; + +		AltosConfigData 	config_data = eeprom.config_data(); + +		AltosEepromRecord	record = null; + +		switch (config_data.log_format) { +		case AltosLib.AO_LOG_FORMAT_FULL: +			record = new AltosEepromRecordFull(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TINY: +			record = new AltosEepromRecordTiny(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEMETRY: +		case AltosLib.AO_LOG_FORMAT_TELESCIENCE: +		case AltosLib.AO_LOG_FORMAT_TELEMEGA: +		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: +			record = new AltosEepromRecordMega(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEMETRUM: +			record = new AltosEepromRecordMetrum(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEMINI2: +		case AltosLib.AO_LOG_FORMAT_TELEMINI3: +		case AltosLib.AO_LOG_FORMAT_EASYMINI1: +		case AltosLib.AO_LOG_FORMAT_EASYMINI2: +			record = new AltosEepromRecordMini(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEGPS: +			record = new AltosEepromRecordGps(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEFIRETWO: +			record = new AltosEepromRecordFireTwo(eeprom); +			break; +		} + +		if (record == null) { +			System.out.printf("failed to parse log format %d\n", config_data.log_format); +			return; +		} +		ordered = new TreeSet<AltosEepromRecord>(); +		int	tick = 0; +		boolean first = true; + +		for (;;) { +			int	t = record.tick(); + +			if (first) { +				tick = t; +				first = false; +			} else { +				while (t < tick - 32767) +					t += 65536; +				tick = t; +			} +			record.wide_tick = tick; +			ordered.add(record); +			if (!record.hasNext()) +				break; +			record = record.next(); +		} +	} + +	public AltosEepromRecordSet(InputStream input) throws IOException { +		this(new AltosEeprom(input)); +	} +} diff --git a/altoslib/AltosEepromRecordTiny.java b/altoslib/AltosEepromRecordTiny.java new file mode 100644 index 00000000..06ee9d54 --- /dev/null +++ b/altoslib/AltosEepromRecordTiny.java @@ -0,0 +1,86 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosEepromRecordTiny extends AltosEepromRecord implements AltosDataProvider { +	public static final int	record_length = 2; + +	private int value() { +		return eeprom.data16(start); +	} + +	public boolean valid(int s) { +		return eeprom.data16(s) != 0xffff; +	} + +	public int cmd() { +		if (start == 0) +			return AltosLib.AO_LOG_FLIGHT; +		if ((value() & 0x8000) != 0) +			return AltosLib.AO_LOG_STATE; +		return AltosLib.AO_LOG_SENSOR; +	} + +	public int tick() { +		int	tick = 0; +		int	step = 10; +		for (int i = 2; i < start; i += 2) +		{ +			int v = eeprom.data16(i); + +			if ((v & 0x8000) != 0) { +				if ((v & 0x7fff) >= AltosLib.ao_flight_drogue) +					step = 100; +			} else { +				tick += step; +			} +		} +		return tick; +	} + +	public void provide_data(AltosDataListener listener) { +		int value = data16(-header_length); + +		listener.set_tick(tick()); +		switch (cmd()) { +		case AltosLib.AO_LOG_FLIGHT: +			listener.set_state(AltosLib.ao_flight_pad); +			listener.cal_data().set_flight(value); +			listener.cal_data().set_boost_tick(); +			break; +		case AltosLib.AO_LOG_STATE: +			listener.set_state(value & 0x7fff); +			break; +		case AltosLib.AO_LOG_SENSOR: +			listener.set_pressure(AltosConvert.barometer_to_pressure(value)); +			break; +		} +	} + +	public AltosEepromRecord next() { +		int	s = next_start(); +		if (s < 0) +			return null; +		return new AltosEepromRecordTiny(eeprom, s); +	} + +	public AltosEepromRecordTiny(AltosEeprom eeprom, int start) { +		super(eeprom, start, record_length); +	} + +	public AltosEepromRecordTiny(AltosEeprom eeprom) { +		this(eeprom, 0); +	} +} diff --git a/altoslib/AltosEepromTM.java b/altoslib/AltosEepromTM.java deleted file mode 100644 index 9a09f926..00000000 --- a/altoslib/AltosEepromTM.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright © 2010 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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. - */ - -package org.altusmetrum.altoslib_11; - -import java.io.*; -import java.util.*; -import java.text.*; - -public class AltosEepromTM extends AltosEeprom { -	public int	a; -	public int	b; - -	public static final int	record_length = 8; - -	public void write(PrintStream out) { -		out.printf("%c %4x %4x %4x\n", cmd, tick, a, b); -	} - -	public int record_length() { return record_length; } - -	public String string() { -		return String.format("%c %4x %4x %4x\n", cmd, tick, a, b); -	} - -	public void update_state(AltosState state) { -		super.update_state(state); - -		AltosGPS	gps; - -		/* Flush any pending GPS changes */ -		if (state.gps_pending) { -			switch (cmd) { -			case AltosLib.AO_LOG_GPS_LAT: -			case AltosLib.AO_LOG_GPS_LON: -			case AltosLib.AO_LOG_GPS_ALT: -			case AltosLib.AO_LOG_GPS_SAT: -			case AltosLib.AO_LOG_GPS_DATE: -				break; -			default: -				state.set_temp_gps(); -				break; -			} -		} - -		switch (cmd) { -		case AltosLib.AO_LOG_FLIGHT: -			state.set_state(AltosLib.ao_flight_pad); -			state.set_ground_accel(a); -			state.set_flight(b); -			state.set_boost_tick(tick); -			break; -		case AltosLib.AO_LOG_SENSOR: -			state.set_accel(a); -			state.set_pressure(AltosConvert.barometer_to_pressure(b)); -			break; -		case AltosLib.AO_LOG_PRESSURE: -			state.set_pressure(AltosConvert.barometer_to_pressure(b)); -			break; -		case AltosLib.AO_LOG_TEMP_VOLT: -			state.set_temperature(AltosConvert.thermometer_to_temperature(a)); -			state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(b)); -			break; -		case AltosLib.AO_LOG_DEPLOY: -			state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(a)); -			state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(b)); -			break; -		case AltosLib.AO_LOG_STATE: -			state.set_state(a); -			break; -		case AltosLib.AO_LOG_GPS_TIME: -			gps = state.make_temp_gps(false); - -			gps.hour = (a & 0xff); -			gps.minute = (a >> 8); -			gps.second = (b & 0xff); - -			int flags = (b >> 8); - -			gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; -			gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; -			gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> -				AltosLib.AO_GPS_NUM_SAT_SHIFT; -			break; -		case AltosLib.AO_LOG_GPS_LAT: -			gps = state.make_temp_gps(false); - -			int lat32 = a | (b << 16); -			gps.lat = (double) lat32 / 1e7; -			break; -		case AltosLib.AO_LOG_GPS_LON: -			gps = state.make_temp_gps(false); - -			int lon32 = a | (b << 16); -			gps.lon = (double) lon32 / 1e7; -			break; -		case AltosLib.AO_LOG_GPS_ALT: -			gps = state.make_temp_gps(false); -			gps.alt = a; -			break; -		case AltosLib.AO_LOG_GPS_SAT: -			gps = state.make_temp_gps(true); -			int svid = a; -			int c_n0 = b >> 8; -			gps.add_sat(svid, c_n0); -			break; -		case AltosLib.AO_LOG_GPS_DATE: -			gps = state.make_temp_gps(false); -			gps.year = (a & 0xff) + 2000; -			gps.month = a >> 8; -			gps.day = b & 0xff; -			break; -		} -	} - -	public AltosEepromTM (AltosEepromChunk chunk, int start) throws ParseException { - -		cmd = chunk.data(start); -		valid = true; - -		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); -		a = chunk.data16(start + 4); -		b = chunk.data16(start + 6); -	} - -	public AltosEepromTM (String line) { -		valid = false; -		tick = 0; -		a = 0; -		b = 0; -		if (line == null) { -			cmd = AltosLib.AO_LOG_INVALID; -		} else { -			try { -				String[] tokens = line.split("\\s+"); - -				if (tokens[0].length() == 1) { -					if (tokens.length != 4) { -						cmd = AltosLib.AO_LOG_INVALID; -					} else { -						cmd = tokens[0].codePointAt(0); -						tick = Integer.parseInt(tokens[1],16); -						valid = true; -						a = Integer.parseInt(tokens[2],16); -						b = Integer.parseInt(tokens[3],16); -					} -				} else { -					cmd = AltosLib.AO_LOG_INVALID; -				} -			} catch (NumberFormatException ne) { -				cmd = AltosLib.AO_LOG_INVALID; -			} -		} -	} - -	public AltosEepromTM(int in_cmd, int in_tick, int in_a, int in_b) { -		valid = true; -		cmd = in_cmd; -		tick = in_tick; -		a = in_a; -		b = in_b; -	} - -	static public LinkedList<AltosEeprom> read(FileInputStream input) { -		LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>(); - -		for (;;) { -			try { -				String line = AltosLib.gets(input); -				if (line == null) -					break; -				AltosEepromTM tm = new AltosEepromTM(line); -				tms.add(tm); -			} catch (IOException ie) { -				break; -			} -		} - -		return tms; -	} - -} diff --git a/altoslib/AltosEepromTMini.java b/altoslib/AltosEepromTMini.java deleted file mode 100644 index 2557f431..00000000 --- a/altoslib/AltosEepromTMini.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright © 2010 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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. - */ - -package org.altusmetrum.altoslib_11; - -import java.io.*; -import java.util.*; -import java.text.*; - -public class AltosEepromTMini extends AltosEeprom { -	public int	i; -	public int	a; -	public int	b; - -	public static final int	record_length = 2; - -	public void write(PrintStream out) { -		out.printf("%c %4x %4x %4x\n", cmd, tick, a, b); -	} - -	public int record_length() { return record_length; } - -	public String string() { -		return String.format("%c %4x %4x %4x\n", cmd, tick, a, b); -	} - -	public void update_state(AltosState state) { -		super.update_state(state); - -		switch (cmd) { -		case AltosLib.AO_LOG_FLIGHT: -			state.set_state(AltosLib.ao_flight_boost); -			state.set_flight(b); -			break; -		case AltosLib.AO_LOG_PRESSURE: -			if (tick == 0) -				state.set_ground_pressure(AltosConvert.barometer_to_pressure(b)); -			else -				state.set_pressure(AltosConvert.barometer_to_pressure(b)); -			break; -		case AltosLib.AO_LOG_STATE: -			state.set_state(a); -			break; -		} -	} - -	public AltosEepromTMini (AltosEepromChunk chunk, int start, AltosState state) throws ParseException { -		int	value = chunk.data16(start); - -		int	i = (chunk.address + start) / record_length; - -		cmd = chunk.data(start); -		valid = true; - -		valid = !chunk.erased(start, record_length); - -		switch (i) { -		case 0: -			cmd = AltosLib.AO_LOG_FLIGHT; -			tick = 0; -			a = 0; -			b = value; -			break; -		case 1: -			cmd = AltosLib.AO_LOG_PRESSURE; -			tick = 0; -			a = 0; -			b = value; -			break; -		default: -			if ((value & 0x8000) != 0) { -				cmd = AltosLib.AO_LOG_STATE; -				tick = state.tick; -				a = value & 0x7fff; -				b = 0; -			} else { -				if (state.ascent) -					tick = state.tick + 10; -				else -					tick = state.tick + 100; -				cmd = AltosLib.AO_LOG_PRESSURE; -				a = 0; -				b = value; -			} -			break; -		} -	} - -	public AltosEepromTMini (String line) { -		valid = false; -		tick = 0; -		a = 0; -		b = 0; -		if (line == null) { -			cmd = AltosLib.AO_LOG_INVALID; -		} else { -			try { -				String[] tokens = line.split("\\s+"); - -				if (tokens[0].length() == 1) { -					if (tokens.length != 4) { -						cmd = AltosLib.AO_LOG_INVALID; -					} else { -						cmd = tokens[0].codePointAt(0); -						tick = Integer.parseInt(tokens[1],16); -						valid = true; -						a = Integer.parseInt(tokens[2],16); -						b = Integer.parseInt(tokens[3],16); -					} -				} else { -					cmd = AltosLib.AO_LOG_INVALID; -				} -			} catch (NumberFormatException ne) { -				cmd = AltosLib.AO_LOG_INVALID; -			} -		} -	} - -	public AltosEepromTMini(int in_cmd, int in_tick, int in_a, int in_b) { -		valid = true; -		cmd = in_cmd; -		tick = in_tick; -		a = in_a; -		b = in_b; -	} - -	static public LinkedList<AltosEeprom> read(FileInputStream input) { -		LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>(); - -		for (;;) { -			try { -				String line = AltosLib.gets(input); -				if (line == null) -					break; -				AltosEepromTMini tm = new AltosEepromTMini(line); -				tms.add(tm); -			} catch (IOException ie) { -				break; -			} -		} - -		return tms; -	} - -} diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java index ef75762a..69f779c1 100644 --- a/altoslib/AltosFile.java +++ b/altoslib/AltosFile.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.File;  import java.util.*; @@ -66,7 +66,7 @@ public class AltosFile extends File {  		     extension);  	} -	public AltosFile(AltosState state) { -		this(state.serial, state.flight, state.receiver_serial, "telem"); +	public AltosFile(AltosCalData cal_data) { +		this(cal_data.serial, cal_data.flight, cal_data.receiver_serial, "telem");  	}  } diff --git a/altoslib/AltosFlash.java b/altoslib/AltosFlash.java index ad573305..c8db1f77 100644 --- a/altoslib/AltosFlash.java +++ b/altoslib/AltosFlash.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosFlashListener.java b/altoslib/AltosFlashListener.java index e15d7ac3..60052133 100644 --- a/altoslib/AltosFlashListener.java +++ b/altoslib/AltosFlashListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosFlashListener {  	public void position(String label, int percent); diff --git a/altoslib/AltosFlightDisplay.java b/altoslib/AltosFlightDisplay.java index c395dc45..8fe33c5e 100644 --- a/altoslib/AltosFlightDisplay.java +++ b/altoslib/AltosFlightDisplay.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {  	void reset(); diff --git a/altoslib/AltosFlightListener.java b/altoslib/AltosFlightListener.java new file mode 100644 index 00000000..d61831a9 --- /dev/null +++ b/altoslib/AltosFlightListener.java @@ -0,0 +1,162 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public abstract class AltosFlightListener { + +	public int	flight; +	public int	serial; +	public int	tick; +	public int	boost_tick; +	public int	state; + +	public double	accel_plus_g; +	public double	accel_minus_g; +	public double	accel; + +	public double	ground_pressure; +	public double	ground_altitude; + +	AltosGPS	temp_gps; +	int		temp_gps_sat_tick; +	int		gps_sequence; + +	/* AltosEepromRecord */ +	public void set_boost_tick(int boost_tick) { +		if (boost_tick != AltosLib.MISSING) +			this.boost_tick = boost_tick; +	} + +	public void set_tick(int tick) { +		if (tick != AltosLib.MISSING) +			this.tick = tick; +	} + +	public double time() { +		if (tick == AltosLib.MISSING) +			return AltosLib.MISSING; +		if (boost_tick != AltosLib.MISSING) +			return (tick - boost_tick) / 100.0; +		else +			return tick / 100.0; +	} + +	public double boost_time() { +		if (boost_tick == AltosLib.MISSING) +			return AltosLib.MISSING; +		return boost_tick / 100.0; +	} + +	public abstract void set_rssi(int rssi, int status); +	public abstract void set_received_time(long received_time); + +	/* AltosEepromRecordFull */ + +	public void set_serial(int serial) { +		if (serial != AltosLib.MISSING) +			this.serial = serial; +	} + +	public void set_state(int state) { +		if (state != AltosLib.MISSING) +			this.state = state; +	} + +	public int state() { return state; } + +	public abstract void set_ground_accel(double ground_accel); +	public void set_flight(int flight) { +		if (flight != AltosLib.MISSING) +			this.flight = flight; +	} +	public int flight() { +		return flight; +	} + +	public abstract void set_accel(double accel); +	public abstract void set_acceleration(double accel); +	public abstract void set_accel_g(double accel_plus_g, double accel_minus_g); +	public abstract void set_pressure(double pa); +	public abstract void set_thrust(double N); + +	public abstract void set_temperature(double deg_c); +	public abstract void set_battery_voltage(double volts); + +	public abstract void set_apogee_voltage(double volts); +	public abstract void set_main_voltage(double volts); + +	public void set_temp_gps() { +		temp_gps = null; +	} + +	public boolean gps_pending() { +		return temp_gps != null; +	} + +	public AltosGPS make_temp_gps(boolean sats) { +		if (temp_gps == null) { +			temp_gps = new AltosGPS(); +		} +		if (sats) { +			if (tick != temp_gps_sat_tick) +				temp_gps.cc_gps_sat = null; +			temp_gps_sat_tick = tick; +		} +		return temp_gps; +	} + +	public void set_ground_pressure(double ground_pressure) { +		if (ground_pressure != AltosLib.MISSING) { +			this.ground_pressure = ground_pressure; +			this.ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); +		} +	} + +	public abstract void set_accel_ground(double along, double across, double through); +	public abstract void set_gyro_zero(double roll, double pitch, double yaw); +	public abstract void check_imu_wrap(AltosIMU imu); +	public abstract void set_imu(AltosIMU imu); +	public abstract void set_mag(AltosMag mag); +	public abstract void set_pyro_voltage(double volts); +	public abstract void set_igniter_voltage(double[] voltage); +	public abstract void set_pyro_fired(int pyro_mask); + +	public void copy(AltosFlightListener old) { +		flight = old.flight; +		serial = old.serial; +		tick = old.tick; +		boost_tick = old.boost_tick; +		accel_plus_g = old.accel_plus_g; +		accel_minus_g = old.accel_minus_g; +		ground_pressure = old.ground_pressure; +		ground_altitude = old.ground_altitude; +		temp_gps = old.temp_gps; +		temp_gps_sat_tick = old.temp_gps_sat_tick; +	} + +	public void init() { +		flight = AltosLib.MISSING; +		serial = AltosLib.MISSING; +		tick = AltosLib.MISSING; +		boost_tick = AltosLib.MISSING; +		accel_plus_g = AltosLib.MISSING; +		accel_minus_g = AltosLib.MISSING; +		accel = AltosLib.MISSING; +		ground_pressure = AltosLib.MISSING; +		ground_altitude = AltosLib.MISSING; +		temp_gps = null; +		temp_gps_sat_tick = AltosLib.MISSING; +	} +} diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java index 250e2236..671bf638 100644 --- a/altoslib/AltosFlightReader.java +++ b/altoslib/AltosFlightReader.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*;  import java.io.*; @@ -31,6 +31,8 @@ public abstract class AltosFlightReader {  	public abstract AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException; +	public abstract AltosCalData cal_data(); +  	public abstract void close(boolean interrupted);  	public void set_frequency(double frequency) throws InterruptedException, TimeoutException { } @@ -45,8 +47,6 @@ public abstract class AltosFlightReader {  	public void save_telemetry_rate() { } -	public void update(AltosState state) throws InterruptedException { } -  	public boolean supports_telemetry(int telemetry) { return false; }  	public boolean supports_telemetry_rate(int telemetry_rate) { return false; } diff --git a/altoslib/AltosFlightSeries.java b/altoslib/AltosFlightSeries.java new file mode 100644 index 00000000..57f1a491 --- /dev/null +++ b/altoslib/AltosFlightSeries.java @@ -0,0 +1,697 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +import java.util.*; + +public class AltosFlightSeries extends AltosDataListener { + +	public ArrayList<AltosTimeSeries> series = new ArrayList<AltosTimeSeries>(); + +	public double	speed_filter_width = 4.0; +	public double	accel_filter_width = 4.0; + +	public int[] indices() { +		int[] indices = new int[series.size()]; +		for (int i = 0; i < indices.length; i++) +			indices[i] = -1; +		step_indices(indices); +		return indices; +	} + +	private double time(int id, int index) { +		AltosTimeSeries		s = series.get(id); + +		if (index < 0) +			return Double.NEGATIVE_INFINITY; + +		if (index < s.values.size()) +			return s.values.get(index).time; +		return Double.POSITIVE_INFINITY; +	} + +	public boolean step_indices(int[] indices) { +		double	min_next = time(0, indices[0]+1); + +		for (int i = 1; i < indices.length; i++) { +			double next = time(i, indices[i]+1); +			if (next < min_next) +				min_next = next; +		} + +		if (min_next == Double.POSITIVE_INFINITY) +			return false; + +		for (int i = 0; i < indices.length; i++) { +			double	t = time(i, indices[i] + 1); + +			if (t <= min_next) +				indices[i]++; +		} +		return true; +	} + +	public double time(int[] indices) { +		double max = time(0, indices[0]); + +		for (int i = 1; i < indices.length; i++) { +			double t = time(i, indices[i]); +			if (t >= max) +				max = t; +		} +		return max; +	} + +	public double value(String name, int[] indices) { +		for (int i = 0; i < indices.length; i++) { +			AltosTimeSeries	s = series.get(i); +			if (s.label.equals(name)) { +				int index = indices[i]; +				if (index < 0) +					index = 0; +				if (index >= s.values.size()) +					index = s.values.size() - 1; +				return s.values.get(index).value; +			} +		} +		return AltosLib.MISSING; +	} + +	public double value(String name, double time) { +		for (AltosTimeSeries s : series) { +			if (s.label.equals(name)) +				return s.value(time); +		} +		return AltosLib.MISSING; +	} + +	public double value_before(String name, double time) { +		for (AltosTimeSeries s : series) { +			if (s.label.equals(name)) +				return s.value_before(time); +		} +		return AltosLib.MISSING; +	} + +	public double value_after(String name, double time) { +		for (AltosTimeSeries s : series) { +			if (s.label.equals(name)) +				return s.value_after(time); +		} +		return AltosLib.MISSING; +	} + +	public AltosTimeSeries make_series(String label, AltosUnits units) { +		return new AltosTimeSeries(label, units); +	} + +	public void add_series(AltosTimeSeries s) { +		for (int e = 0; e < series.size(); e++) { +			if (s.compareTo(series.get(e)) < 0){ +				series.add(e, s); +				return; +			} +		} +		series.add(s); +	} + +	public AltosTimeSeries add_series(String label, AltosUnits units) { +		AltosTimeSeries s = make_series(label, units); +		add_series(s); +		return s; +	} + +	public void remove_series(AltosTimeSeries s) { +		series.remove(s); +	} + +	public boolean has_series(String label) { +		for (AltosTimeSeries s : series) +			if (s.label.equals(label)) +				return true; +		return false; +	} + +	public AltosTimeSeries state_series; + +	public static final String state_name = "State"; + +	public void set_state(int state) { + +		if (state == AltosLib.ao_flight_pad) +			return; + +		if (state_series == null) +			state_series = add_series(state_name, AltosConvert.state_name); +		else if (this.state == state) +			return; +		this.state = state; +		state_series.add(time(), state); +	} + +	public AltosTimeSeries	accel_series; + +	public static final String accel_name = "Accel"; + +	public AltosTimeSeries	vert_accel_series; + +	public static final String vert_accel_name = "Vertical Accel"; + +	public void set_acceleration(double acceleration) { +		if (acceleration == AltosLib.MISSING) +			return; +		if (accel_series == null) +			accel_series = add_series(accel_name, AltosConvert.accel); + +		accel_series.add(time(), acceleration); +	} + +	private void compute_accel() { +		if (accel_series != null) +			return; + +		if (speed_series != null) { +			AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed); +			speed_series.filter(temp_series, accel_filter_width); +			accel_series = add_series(accel_name, AltosConvert.accel); +			temp_series.differentiate(accel_series); +		} +	} + +	public void set_received_time(long received_time) { +	} + +	public AltosTimeSeries rssi_series; + +	public static final String rssi_name = "RSSI"; + +	public AltosTimeSeries status_series; + +	public static final String status_name = "Radio Status"; + +	public void set_rssi(int rssi, int status) { +		if (rssi_series == null) { +			rssi_series = add_series(rssi_name, null); +			status_series = add_series(status_name, null); +		} +		rssi_series.add(time(), rssi); +		status_series.add(time(), status); +	} + +	public AltosTimeSeries pressure_series; + +	public static final String pressure_name = "Pressure"; + +	public AltosTimeSeries altitude_series; + +	public static final String altitude_name = "Altitude"; + +	public AltosTimeSeries height_series; + +	public static final String height_name = "Height"; + +	public  void set_pressure(double pa) { +		if (pa == AltosLib.MISSING) +			return; + +		if (pressure_series == null) +			pressure_series = add_series(pressure_name, AltosConvert.pressure); +		pressure_series.add(time(), pa); +		if (altitude_series == null) +			altitude_series = add_series(altitude_name, AltosConvert.height); + +		if (cal_data().ground_pressure == AltosLib.MISSING) +			cal_data().set_ground_pressure(pa); + +		double altitude = AltosConvert.pressure_to_altitude(pa); +		altitude_series.add(time(), altitude); +	} + +	private void compute_height() { +		double ground_altitude = cal_data().ground_altitude; +		if (height_series == null && ground_altitude != AltosLib.MISSING && altitude_series != null) { +			height_series = add_series(height_name, AltosConvert.height); +			for (AltosTimeValue alt : altitude_series) +				height_series.add(alt.time, alt.value - ground_altitude); +		} + +		if (gps_height == null && cal_data().gps_pad != null && cal_data().gps_pad.alt != AltosLib.MISSING && gps_altitude != null) { +			double gps_ground_altitude = cal_data().gps_pad.alt; +			gps_height = add_series(gps_height_name, AltosConvert.height); +			for (AltosTimeValue gps_alt : gps_altitude) +				gps_height.add(gps_alt.time, gps_alt.value - gps_ground_altitude); +		} +	} + +	public AltosTimeSeries speed_series; + +	public static final String speed_name = "Speed"; + +	private void compute_speed() { +		if (speed_series != null) +			return; + +		AltosTimeSeries	alt_speed_series = null; +		AltosTimeSeries accel_speed_series = null; + +		if (altitude_series != null) { +			AltosTimeSeries temp_series = make_series(altitude_name, AltosConvert.height); +			altitude_series.filter(temp_series, speed_filter_width); + +			alt_speed_series = make_series(speed_name, AltosConvert.speed); +			temp_series.differentiate(alt_speed_series); +		} +		if (accel_series != null) { + +			if (orient_series != null) { +				vert_accel_series = add_series(vert_accel_name, AltosConvert.accel); + +				for (AltosTimeValue a : accel_series) { +					double	orient = orient_series.value(a.time); +					double	a_abs = a.value + AltosConvert.gravity; +					double	v_a = a_abs * Math.cos(AltosConvert.degrees_to_radians(orient)) - AltosConvert.gravity; + +					vert_accel_series.add(a.time, v_a); +				} +			} + +			AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed); + +			if (vert_accel_series != null) +				vert_accel_series.integrate(temp_series); +			else +				accel_series.integrate(temp_series); + +			accel_speed_series = make_series(speed_name, AltosConvert.speed); +			temp_series.filter(accel_speed_series, 0.1); +		} + +		if (alt_speed_series != null && accel_speed_series != null) { +			double	apogee_time = AltosLib.MISSING; +			if (state_series != null) { +				for (AltosTimeValue d : state_series) { +					if (d.value >= AltosLib.ao_flight_drogue){ +						apogee_time = d.time; +						break; +					} +				} +			} +			if (apogee_time == AltosLib.MISSING) { +				speed_series = alt_speed_series; +			} else { +				speed_series = make_series(speed_name, AltosConvert.speed); +				for (AltosTimeValue d : accel_speed_series) { +					if (d.time <= apogee_time) +						speed_series.add(d); +				} +				for (AltosTimeValue d : alt_speed_series) { +					if (d.time > apogee_time) +						speed_series.add(d); +				} + +			} +		} else if (alt_speed_series != null) { +			speed_series = alt_speed_series; +		} else if (accel_speed_series != null) { +			speed_series = accel_speed_series; +		} +		if (speed_series != null) +			add_series(speed_series); +	} + +	public AltosTimeSeries orient_series; + +	public static final String orient_name = "Tilt Angle"; + +	private void compute_orient() { + +		if (orient_series != null) +			return; + +		if (accel_ground_across == AltosLib.MISSING) +			return; + +		if (cal_data().pad_orientation == AltosLib.MISSING) +			return; + +		if (cal_data().accel_zero_across == AltosLib.MISSING) +			return; + +		AltosRotation rotation = new AltosRotation(AltosIMU.convert_accel(accel_ground_across - cal_data().accel_zero_across), +							   AltosIMU.convert_accel(accel_ground_through - cal_data().accel_zero_through), +							   AltosIMU.convert_accel(accel_ground_along - cal_data().accel_zero_along), +							   cal_data().pad_orientation); +		double prev_time = ground_time; + +		orient_series = add_series(orient_name, AltosConvert.orient); +		orient_series.add(ground_time, rotation.tilt()); + +		for (AltosTimeValue roll_v : gyro_roll) { +			double	time = roll_v.time; +			double	dt = time - prev_time; + +			if (dt > 0) { +				double	roll = AltosConvert.degrees_to_radians(roll_v.value) * dt; +				double	pitch = AltosConvert.degrees_to_radians(gyro_pitch.value(time)) * dt; +				double	yaw = AltosConvert.degrees_to_radians(gyro_yaw.value(time)) * dt; + +				rotation.rotate(pitch, yaw, roll); +				orient_series.add(time, rotation.tilt()); +			} +			prev_time = time; +		} +	} + +	public AltosTimeSeries	kalman_height_series, kalman_speed_series, kalman_accel_series; + +	public static final String kalman_height_name = "Kalman Height"; +	public static final String kalman_speed_name = "Kalman Speed"; +	public static final String kalman_accel_name = "Kalman Accel"; + +	public void set_kalman(double height, double speed, double acceleration) { +		if (kalman_height_series == null) { +			kalman_height_series = add_series(kalman_height_name, AltosConvert.height); +			kalman_speed_series = add_series(kalman_speed_name, AltosConvert.speed); +			kalman_accel_series = add_series(kalman_accel_name, AltosConvert.accel); +		} +		kalman_height_series.add(time(), height); +		kalman_speed_series.add(time(), speed); +		kalman_accel_series.add(time(), acceleration); +	} + +	public AltosTimeSeries thrust_series; + +	public static final String thrust_name = "Thrust"; + +	public	void set_thrust(double N) { +		if (thrust_series == null) +			thrust_series = add_series(thrust_name, AltosConvert.force); +		thrust_series.add(time(), N); +	} + +	public AltosTimeSeries temperature_series; + +	public static final String temperature_name = "Temperature"; + +	public  void set_temperature(double deg_c) { +		if (temperature_series == null) +			temperature_series = add_series(temperature_name, AltosConvert.temperature); +		temperature_series.add(time(), deg_c); +	} + +	public AltosTimeSeries battery_voltage_series; + +	public static final String battery_voltage_name = "Battery Voltage"; + +	public void set_battery_voltage(double volts) { +		if (volts == AltosLib.MISSING) +			return; +		if (battery_voltage_series == null) +			battery_voltage_series = add_series(battery_voltage_name, AltosConvert.voltage); +		battery_voltage_series.add(time(), volts); +	} + +	public AltosTimeSeries apogee_voltage_series; + +	public static final String apogee_voltage_name = "Apogee Voltage"; + +	public void set_apogee_voltage(double volts) { +		if (volts == AltosLib.MISSING) +			return; +		if (apogee_voltage_series == null) +			apogee_voltage_series = add_series(apogee_voltage_name, AltosConvert.voltage); +		apogee_voltage_series.add(time(), volts); +	} + +	public AltosTimeSeries main_voltage_series; + +	public static final String main_voltage_name = "Main Voltage"; + +	public void set_main_voltage(double volts) { +		if (volts == AltosLib.MISSING) +			return; +		if (main_voltage_series == null) +			main_voltage_series = add_series(main_voltage_name, AltosConvert.voltage); +		main_voltage_series.add(time(), volts); +	} + +	public ArrayList<AltosGPSTimeValue> gps_series; + +	public AltosGPS gps_before(double time) { +		AltosGPS gps = null; +		for (AltosGPSTimeValue gtv : gps_series) +			if (gtv.time <= time) +				gps = gtv.gps; +			else +				break; +		return gps; +	} + +	public AltosTimeSeries	sats_in_view; +	public AltosTimeSeries sats_in_soln; +	public AltosTimeSeries gps_altitude; +	public AltosTimeSeries gps_height; +	public AltosTimeSeries gps_ground_speed; +	public AltosTimeSeries gps_ascent_rate; +	public AltosTimeSeries gps_course; +	public AltosTimeSeries gps_speed; +	public AltosTimeSeries gps_pdop, gps_vdop, gps_hdop; + +	public static final String sats_in_view_name = "Satellites in view"; +	public static final String sats_in_soln_name = "Satellites in solution"; +	public static final String gps_altitude_name = "GPS Altitude"; +	public static final String gps_height_name = "GPS Height"; +	public static final String gps_ground_speed_name = "GPS Ground Speed"; +	public static final String gps_ascent_rate_name = "GPS Ascent Rate"; +	public static final String gps_course_name = "GPS Course"; +	public static final String gps_speed_name = "GPS Speed"; +	public static final String gps_pdop_name = "GPS Dilution of Precision"; +	public static final String gps_vdop_name = "GPS Vertical Dilution of Precision"; +	public static final String gps_hdop_name = "GPS Horizontal Dilution of Precision"; + +	public void set_gps(AltosGPS gps) { +		if (gps_series == null) +			gps_series = new ArrayList<AltosGPSTimeValue>(); +		gps_series.add(new AltosGPSTimeValue(time(), gps)); + +		if (sats_in_soln == null) { +			sats_in_soln = add_series(sats_in_soln_name, null); +		} +		sats_in_soln.add(time(), gps.nsat); +		if (gps.pdop != AltosLib.MISSING) { +			if (gps_pdop == null) +				gps_pdop = add_series(gps_pdop_name, null); +			gps_pdop.add(time(), gps.pdop); +		} +		if (gps.hdop != AltosLib.MISSING) { +			if (gps_hdop == null) +				gps_hdop = add_series(gps_hdop_name, null); +			gps_hdop.add(time(), gps.hdop); +		} +		if (gps.vdop != AltosLib.MISSING) { +			if (gps_vdop == null) +				gps_vdop = add_series(gps_vdop_name, null); +			gps_vdop.add(time(), gps.vdop); +		} +		if (gps.locked) { +			if (gps.alt != AltosLib.MISSING) { +				if (gps_altitude == null) +					gps_altitude = add_series(gps_altitude_name, AltosConvert.height); +				gps_altitude.add(time(), gps.alt); +			} +			if (gps.ground_speed != AltosLib.MISSING) { +				if (gps_ground_speed == null) +					gps_ground_speed = add_series(gps_ground_speed_name, AltosConvert.speed); +				gps_ground_speed.add(time(), gps.ground_speed); +			} +			if (gps.climb_rate != AltosLib.MISSING) { +				if (gps_ascent_rate == null) +					gps_ascent_rate = add_series(gps_ascent_rate_name, AltosConvert.speed); +				gps_ascent_rate.add(time(), gps.climb_rate); +			} +			if (gps.course != AltosLib.MISSING) { +				if (gps_course == null) +					gps_course = add_series(gps_course_name, null); +				gps_course.add(time(), gps.course); +			} +			if (gps.ground_speed != AltosLib.MISSING && gps.climb_rate != AltosLib.MISSING) { +				if (gps_speed == null) +					gps_speed = add_series(gps_speed_name, null); +				gps_speed.add(time(), Math.sqrt(gps.ground_speed * gps.ground_speed + +								gps.climb_rate * gps.climb_rate)); +			} +		} +		if (gps.cc_gps_sat != null) { +			if (sats_in_view == null) +				sats_in_view = add_series(sats_in_view_name, null); +			sats_in_view.add(time(), gps.cc_gps_sat.length); +		} +	} + +	public static final String accel_along_name = "Accel Along"; +	public static final String accel_across_name = "Accel Across"; +	public static final String accel_through_name = "Accel Through"; + +	public AltosTimeSeries accel_along, accel_across, accel_through; + +	public static final String gyro_roll_name = "Roll Rate"; +	public static final String gyro_pitch_name = "Pitch Rate"; +	public static final String gyro_yaw_name = "Yaw Rate"; + +	public AltosTimeSeries gyro_roll, gyro_pitch, gyro_yaw; + +	public static final String mag_along_name = "Magnetic Field Along"; +	public static final String mag_across_name = "Magnetic Field Across"; +	public static final String mag_through_name = "Magnetic Field Through"; + +	public AltosTimeSeries mag_along, mag_across, mag_through; + +	public  void set_accel(double along, double across, double through) { +		if (accel_along == null) { +			accel_along = add_series(accel_along_name, AltosConvert.accel); +			accel_across = add_series(accel_across_name, AltosConvert.accel); +			accel_through = add_series(accel_through_name, AltosConvert.accel); +		} +		accel_along.add(time(), along); +		accel_across.add(time(), across); +		accel_through.add(time(), through); +	} + +	private double	accel_ground_along = AltosLib.MISSING; +	private double	accel_ground_across = AltosLib.MISSING; +	private double	accel_ground_through = AltosLib.MISSING; + +	private double		ground_time; + +	public  void set_accel_ground(double along, double across, double through) { +		accel_ground_along = along; +		accel_ground_across = across; +		accel_ground_through = through; +		ground_time = time(); +	} + +	public  void set_gyro(double roll, double pitch, double yaw) { +		if (gyro_roll == null) { +			gyro_roll = add_series(gyro_roll_name, AltosConvert.rotation_rate); +			gyro_pitch = add_series(gyro_pitch_name, AltosConvert.rotation_rate); +			gyro_yaw = add_series(gyro_yaw_name, AltosConvert.rotation_rate); +		} +		gyro_roll.add(time(), roll); +		gyro_pitch.add(time(), pitch); +		gyro_yaw.add(time(), yaw); +	} + +	public  void set_mag(double along, double across, double through) { +		if (mag_along == null) { +			mag_along = add_series(mag_along_name, AltosConvert.magnetic_field); +			mag_across = add_series(mag_across_name, AltosConvert.magnetic_field); +			mag_through = add_series(mag_through_name, AltosConvert.magnetic_field); +		} +		mag_along.add(time(), along); +		mag_across.add(time(), across); +		mag_through.add(time(), through); +	} + +	public void set_orient(double orient) { +		if (orient_series == null) +			orient_series = add_series(orient_name, AltosConvert.orient); +		orient_series.add(time(), orient); +	} + +	public static final String pyro_voltage_name = "Pyro Voltage"; + +	public AltosTimeSeries pyro_voltage; + +	public  void set_pyro_voltage(double volts) { +		if (pyro_voltage == null) +			pyro_voltage = add_series(pyro_voltage_name, AltosConvert.voltage); +		pyro_voltage.add(time(), volts); +	} + +	private static String[] igniter_voltage_names; + +	public String igniter_voltage_name(int channel) { +		if (igniter_voltage_names == null || igniter_voltage_names.length <= channel) { +			String[] new_igniter_voltage_names = new String[channel + 1]; +			int	i = 0; + +			if (igniter_voltage_names != null) { +				for (; i < igniter_voltage_names.length; i++) +					new_igniter_voltage_names[i] = igniter_voltage_names[i]; +			} +			for (; i < channel+1; i++) +				new_igniter_voltage_names[i] = AltosLib.igniter_name(i); +			igniter_voltage_names = new_igniter_voltage_names; +		} +		return igniter_voltage_names[channel]; +	} + +	public AltosTimeSeries[] igniter_voltage; + +	public  void set_igniter_voltage(double[] voltage) { +		int channels = voltage.length; +		if (igniter_voltage == null || igniter_voltage.length <= channels) { +			AltosTimeSeries[]	new_igniter_voltage = new AltosTimeSeries[channels + 1]; +			int			i = 0; + +			if (igniter_voltage != null) { +				for (; i < igniter_voltage.length; i++) +					new_igniter_voltage[i] = igniter_voltage[i]; +			} +			for (; i < channels; i++) +				new_igniter_voltage[i] = add_series(igniter_voltage_name(i), AltosConvert.voltage); +			igniter_voltage = new_igniter_voltage; +		} +		for (int channel = 0; channel < voltage.length; channel++) +			igniter_voltage[channel].add(time(), voltage[channel]); +	} + +	public static final String pyro_fired_name = "Pyro Channel State"; + +	public AltosTimeSeries pyro_fired_series; + +	int	last_pyro_mask; + +	public  void set_pyro_fired(int pyro_mask) { +		if (pyro_fired_series == null) +			pyro_fired_series = add_series(pyro_fired_name, AltosConvert.pyro_name); +		for (int channel = 0; channel < 32; channel++) { +			if ((last_pyro_mask & (1 << channel)) == 0 && +			    (pyro_mask & (1 << channel)) != 0) { +				pyro_fired_series.add(time(), channel); +			} +		} +		last_pyro_mask = pyro_mask; +	} + +	public void set_companion(AltosCompanion companion) { +	} + +	public void finish() { +		compute_orient(); +		compute_speed(); +		compute_accel(); +		compute_height(); +	} + +	public AltosTimeSeries[] series() { +		finish(); +		return series.toArray(new AltosTimeSeries[0]); +	} + +	public AltosFlightSeries(AltosCalData cal_data) { +		super(cal_data); +	} +} diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java index 98f13dac..6f8732cf 100644 --- a/altoslib/AltosFlightStats.java +++ b/altoslib/AltosFlightStats.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; @@ -25,15 +25,17 @@ public class AltosFlightStats {  	public double		max_gps_height;  	public double		max_speed;  	public double		max_acceleration; -	public double[]	state_speed = new double[AltosLib.ao_flight_invalid + 1]; -	public double[]	state_accel = new double[AltosLib.ao_flight_invalid + 1]; -	public int[]		state_count = new int[AltosLib.ao_flight_invalid + 1]; -	public double[]	state_start = new double[AltosLib.ao_flight_invalid + 1]; -	public double[]	state_end = new double[AltosLib.ao_flight_invalid + 1]; +	public double[]		state_speed = new double[AltosLib.ao_flight_invalid + 1]; +	public double[]		state_accel = new double[AltosLib.ao_flight_invalid + 1]; +	public double[]		state_time = new double[AltosLib.ao_flight_invalid + 1]; +	public String		product; +	public String		firmware_version;  	public int		serial;  	public int		flight;  	public int		year, month, day;  	public int		hour, minute, second; +	public double		boost_time; +	public double		landed_time;  	public double		lat, lon;  	public double		pad_lat, pad_lon;  	public boolean		has_flight_data; @@ -46,65 +48,133 @@ public class AltosFlightStats {  	public boolean		has_imu;  	public boolean		has_mag;  	public boolean		has_orient; -	public int		num_ignitor; +	public int		num_igniter; -	double landed_time(AltosStateIterable states) { -		AltosState state = null; +	double landed_time(AltosFlightSeries series) { +		double	landed_state_time = AltosLib.MISSING; -		for (AltosState s : states) { -			state = s; -			if (state.state() == AltosLib.ao_flight_landed) -				break; +		double	prev_state_time = AltosLib.MISSING; +		if (series.state_series != null) { +			for (AltosTimeValue state : series.state_series) { +				if (state.value == AltosLib.ao_flight_landed) { +					landed_state_time = state.time; +					break; +				} else { +					prev_state_time = state.time; +				} +			}  		} -		if (state == null) -			return AltosLib.MISSING; +		if (landed_state_time == AltosLib.MISSING && series.height_series != null) +			landed_state_time = series.height_series.get(series.height_series.size()-1).time; -		double	landed_height = state.height(); +		double landed_height = AltosLib.MISSING; + +		if (series.height_series != null) { +			for (AltosTimeValue height : series.height_series) { +				landed_height = height.value; +				if (height.time >= landed_state_time) +					break; +			} +		} -		state = null; +		if (landed_height == AltosLib.MISSING) +			return AltosLib.MISSING;  		boolean	above = true;  		double	landed_time = AltosLib.MISSING; -		for (AltosState s : states) { -			state = s; - -			if (state.height() > landed_height + 10) { -				above = true; -			} else { -				if (above && Math.abs(state.height() - landed_height) < 2) { -					above = false; -					landed_time = state.time; +		if (series.height_series != null) { +			for (AltosTimeValue height : series.height_series) { +				if (height.value > landed_height + 10) { +					above = true; +				} else { +					if (above && Math.abs(height.value - landed_height) < 2) { +						above = false; +						landed_time = height.time; +					}  				}  			}  		} + +		if (landed_time == AltosLib.MISSING || (prev_state_time != AltosLib.MISSING && landed_time < prev_state_time)) +			landed_time = landed_state_time;  		return landed_time;  	} -	double boost_time(AltosStateIterable states) { -		double boost_time = AltosLib.MISSING; -		AltosState	state = null; +	double boost_time(AltosFlightSeries series) { +		double 		boost_time = AltosLib.MISSING; +		double		boost_state_time = AltosLib.MISSING; -		for (AltosState s : states) { -			state = s; -			if (state.acceleration() < 1) -				boost_time = state.time; -			if (state.state() >= AltosLib.ao_flight_boost && state.state() <= AltosLib.ao_flight_landed) -				break; +		if (series.state_series != null) { +			for (AltosTimeValue state : series.state_series) { +				if (state.value >= AltosLib.ao_flight_boost && state.value <= AltosLib.ao_flight_landed) { +					boost_state_time = state.time; +					break; +				} +			}  		} -		if (state == null) -			return AltosLib.MISSING; - +		if (series.accel_series != null) { +			for (AltosTimeValue accel : series.accel_series) { +				if (accel.value < 1) +					boost_time = accel.time; +				if (boost_state_time != AltosLib.MISSING && accel.time >= boost_state_time) +					break; +			} +		} +		if (boost_time == AltosLib.MISSING) +			boost_time = boost_state_time;  		return boost_time;  	} +	private void add_times(AltosFlightSeries series, int state, double start_time, double end_time) { +		double delta_time = end_time - start_time; +		if (0 <= state && state <= AltosLib.ao_flight_invalid && delta_time > 0) { +			speeds[state].value += series.speed_series.average(start_time, end_time) * delta_time; +			speeds[state].time += delta_time; +			accels[state].value += series.accel_series.average(start_time, end_time) * delta_time; +			accels[state].time += delta_time; +			state_time[state] += delta_time; + +			if (state == AltosLib.ao_flight_boost) { +				AltosTimeValue tv_speed = series.speed_series.max(start_time, end_time); +				if (tv_speed != null && (max_speed == AltosLib.MISSING || tv_speed.value > max_speed)) +					max_speed = tv_speed.value; +				AltosTimeValue tv_accel = series.accel_series.max(start_time, end_time); +				if (tv_accel != null && (max_acceleration == AltosLib.MISSING || tv_accel.value > max_acceleration)) +					max_acceleration = tv_accel.value; +			} +		} +	} + +	AltosTimeValue[]	speeds = new AltosTimeValue[AltosLib.ao_flight_invalid + 1]; +	AltosTimeValue[]	accels = new AltosTimeValue[AltosLib.ao_flight_invalid + 1]; -	public AltosFlightStats(AltosStateIterable states) throws InterruptedException, IOException { -		double		boost_time = boost_time(states); -		double		end_time = 0; -		double		landed_time = landed_time(states); +	public AltosFlightStats(AltosFlightSeries series) { +		AltosCalData	cal_data = series.cal_data(); + +		series.finish(); + +		boost_time = boost_time(series); +		landed_time = landed_time(series); + +		if (series.state_series != null){ +			boolean fixed_boost = false; +			boolean fixed_landed = false; +			for (AltosTimeValue state : series.state_series) { +				if ((int) state.value == AltosLib.ao_flight_boost) +					if (boost_time != AltosLib.MISSING && !fixed_boost) { +						state.time = boost_time; +						fixed_boost = true; +					} +				if ((int) state.value == AltosLib.ao_flight_landed) +					if (landed_time != AltosLib.MISSING && !fixed_landed) { +						state.time = landed_time; +						fixed_landed = true; +					} +			} +		}  		year = month = day = AltosLib.MISSING;  		hour = minute = second = AltosLib.MISSING; @@ -120,96 +190,75 @@ public class AltosFlightStats {  		has_mag = false;  		has_orient = false; -		for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) { -			state_count[s] = 0; -			state_speed[s] = 0.0; -			state_accel[s] = 0.0; +		for (int s = 0; s < AltosLib.ao_flight_invalid + 1; s++) { +			state_speed[s] = AltosLib.MISSING; +			state_accel[s] = AltosLib.MISSING; +			state_time[s] = 0; +			speeds[s] = new AltosTimeValue(0, 0); +			accels[s] = new AltosTimeValue(0, 0);  		} -		for (AltosState state : states) { -			if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING) -				serial = state.serial; -			if (flight == AltosLib.MISSING && state.flight != AltosLib.MISSING) -				flight = state.flight; -			if (state.battery_voltage != AltosLib.MISSING) -				has_battery = true; -			if (state.main_voltage != AltosLib.MISSING) -				has_flight_adc = true; -			if (state.rssi != AltosLib.MISSING) -				has_rssi = true; -			end_time = state.time; - -			if (state.pressure() != AltosLib.MISSING) -				has_flight_data = true; - -			int state_id = state.state(); -			if (boost_time != AltosLib.MISSING && state.time >= boost_time && state_id < AltosLib.ao_flight_boost) { -				state_id = AltosLib.ao_flight_boost; -			} -			if (landed_time != AltosLib.MISSING && state.time >= landed_time && state_id < AltosLib.ao_flight_landed) { -				state_id = AltosLib.ao_flight_landed; -			} +		max_speed = AltosLib.MISSING; +		max_acceleration = AltosLib.MISSING; -			if (state.gps != null && state.gps.locked) { -				year = state.gps.year; -				month = state.gps.month; -				day = state.gps.day; -				hour = state.gps.hour; -				minute = state.gps.minute; -				second = state.gps.second; +		if (series.state_series != null) { +			AltosTimeValue prev = null; +			for (AltosTimeValue state : series.state_series) { +				if (prev != null) +					add_times(series, (int) prev.value, prev.time, state.time); +				prev = state;  			} -			max_height = state.max_height(); -			max_speed = state.max_speed(); -			max_acceleration = state.max_acceleration(); -			max_gps_height = state.max_gps_height(); - -			if (0 <= state_id && state_id < AltosLib.ao_flight_invalid) { -				double acceleration = state.acceleration(); -				double speed = state.speed(); -				if (acceleration != AltosLib.MISSING && speed != AltosLib.MISSING) { -					state_accel[state_id] += acceleration; -					state_speed[state_id] += speed; -					state_count[state_id]++; +			if (prev != null) +				add_times(series, (int) prev.value, prev.time, series.accel_series.last().time); +		} + +		for (int s = 0; s <= AltosLib.ao_flight_invalid; s++) { +			if (speeds[s].time > 0) +				state_speed[s] = speeds[s].value / speeds[s].time; +			if (accels[s].time > 0) +				state_accel[s] = accels[s].value / accels[s].time; +		} + +		product = cal_data.product; +		firmware_version = cal_data.firmware_version; +		serial = cal_data.serial; +		flight = cal_data.flight; + +		has_battery = series.battery_voltage_series != null; +		has_flight_adc = series.main_voltage_series != null; +		has_rssi = series.rssi_series != null; +		has_flight_data = series.pressure_series != null; + +		AltosGPS gps = series.cal_data().gps_pad; + +		if (gps != null) { +			year = gps.year; +			month = gps.month; +			day = gps.day; +			hour = gps.hour; +			minute = gps.minute; +			second = gps.second; +			has_gps = true; +			lat = pad_lat = gps.lat; +			lon = pad_lon = gps.lon; +			for (AltosGPSTimeValue gtv : series.gps_series) { +				gps = gtv.gps; +				if (gps.locked && gps.nsat >= 4) { +					lat = gps.lat; +					lon = gps.lon;  				} -				if (state_start[state_id] == 0.0) -					state_start[state_id] = state.time; -				if (state_end[state_id] < state.time) -					state_end[state_id] = state.time; -			} -			if (state.pad_lat != AltosLib.MISSING) { -				pad_lat = state.pad_lat; -				pad_lon = state.pad_lon;  			} -			if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { -				lat = state.gps.lat; -				lon = state.gps.lon; -				has_gps = true; -				if (state.gps.cc_gps_sat != null) -					has_gps_sats = true; -				if (state.gps.course != AltosLib.MISSING) -					has_gps_detail = true; -			} -			if (state.imu != null) -				has_imu = true; -			if (state.mag != null) -				has_mag = true; -			if (state.orient() != AltosLib.MISSING) -				has_orient = true; -			if (state.ignitor_voltage != null && state.ignitor_voltage.length > num_ignitor) -				num_ignitor = state.ignitor_voltage.length; +  		} -		for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) { -			if (state_count[s] > 0) { -				state_speed[s] /= state_count[s]; -				state_accel[s] /= state_count[s]; -			} else { -				state_speed[s] = AltosLib.MISSING; -				state_accel[s] = AltosLib.MISSING; -			} -			if (state_start[s] == 0) -				state_start[s] = end_time; -			if (state_end[s] == 0) -				state_end[s] = end_time; + +		max_height = AltosLib.MISSING; +		if (series.height_series != null) +			max_height = series.height_series.max().value; +		max_gps_height = AltosLib.MISSING; +		if (series.gps_height != null) { +			AltosTimeValue tv = series.gps_height.max(); +			if (tv != null) +				max_gps_height = tv.value;  		}  	}  } diff --git a/altoslib/AltosFontListener.java b/altoslib/AltosFontListener.java index c7f339a0..97947d0b 100644 --- a/altoslib/AltosFontListener.java +++ b/altoslib/AltosFontListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosFontListener {  	void font_size_changed(int font_size); diff --git a/altoslib/AltosForce.java b/altoslib/AltosForce.java new file mode 100644 index 00000000..47fb900c --- /dev/null +++ b/altoslib/AltosForce.java @@ -0,0 +1,49 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosForce extends AltosUnits { + +	public double value(double v, boolean imperial_units) { +		if (imperial_units) +			return AltosConvert.n_to_lb(v); +		return v; +	} + +	public double inverse(double v, boolean imperial_units) { +		if (imperial_units) +			return AltosConvert.lb_to_n(v); +		return v; +	} + +	public String show_units(boolean imperial_units) { +		if (imperial_units) +			return "lbs"; +		return "N"; +	} + +	public String say_units(boolean imperial_units) { +		if (imperial_units) +			return "pounds"; +		return "newtons"; +	} + +	public int show_fraction(int width, boolean imperial_units) { +		return width / 9; +	} +} diff --git a/altoslib/AltosFrequency.java b/altoslib/AltosFrequency.java index 3b2a445a..6838be8a 100644 --- a/altoslib/AltosFrequency.java +++ b/altoslib/AltosFrequency.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index 0b30ed45..b6ca3576 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*;  import java.util.concurrent.*; @@ -383,17 +383,13 @@ public class AltosGPS implements Cloneable {  		}  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try { -			AltosGPS	gps = new AltosGPS(link, config_data); - -			if (gps != null) { -				state.set_gps(gps, state.gps_sequence++); -				return; -			} +			AltosGPS gps = new AltosGPS(link, link.config_data()); +			if (gps != null) +				listener.set_gps(gps);  		} catch (TimeoutException te) {  		} -		state.set_gps(null, 0);  	}  	public AltosGPS (AltosLink link, AltosConfigData config_data) throws TimeoutException, InterruptedException { diff --git a/altoslib/AltosGPSSat.java b/altoslib/AltosGPSSat.java index e2f0f380..8d3b316a 100644 --- a/altoslib/AltosGPSSat.java +++ b/altoslib/AltosGPSSat.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.text.*; diff --git a/altoslib/AltosGPSTimeValue.java b/altoslib/AltosGPSTimeValue.java new file mode 100644 index 00000000..e15c60e3 --- /dev/null +++ b/altoslib/AltosGPSTimeValue.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosGPSTimeValue { +	public double	time; +	public AltosGPS	gps; + +	public AltosGPSTimeValue(double time, AltosGPS gps) { +		this.time = time; +		this.gps = gps; +	} +} diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java index 6e5bd362..f1cb1940 100644 --- a/altoslib/AltosGreatCircle.java +++ b/altoslib/AltosGreatCircle.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.lang.Math;  import java.io.*; diff --git a/altoslib/AltosHeight.java b/altoslib/AltosHeight.java index 0cd495fb..668080f1 100644 --- a/altoslib/AltosHeight.java +++ b/altoslib/AltosHeight.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosHeight extends AltosUnits { diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java index e746b649..7ab121ad 100644 --- a/altoslib/AltosHexfile.java +++ b/altoslib/AltosHexfile.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.LinkedList; diff --git a/altoslib/AltosHexsym.java b/altoslib/AltosHexsym.java index 2eb08f75..4f56af9a 100644 --- a/altoslib/AltosHexsym.java +++ b/altoslib/AltosHexsym.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosHexsym {  	String	name; diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index f6cadf1d..dee28a92 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -16,30 +16,32 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.*;  import java.io.*;  public class AltosIMU implements Cloneable { -	public int		accel_along; -	public int		accel_across; -	public int		accel_through; +	public int		accel_x; +	public int		accel_y; +	public int		accel_z; -	public int		gyro_roll; -	public int		gyro_pitch; -	public int		gyro_yaw; +	public int		gyro_x; +	public int		gyro_y; +	public int		gyro_z;  	public static final double	counts_per_g = 2048.0;  	public static double convert_accel(double counts) { -		return counts / counts_per_g * (-AltosConvert.GRAVITATIONAL_ACCELERATION); +		return counts / counts_per_g * AltosConvert.gravity;  	} -	public static final double	counts_per_degsec = 16.4; +	/* In radians */ +	public static final double 	GYRO_FULLSCALE_DEGREES = 2000.0; +	public static final double	GYRO_COUNTS = 32767.0; -	public static double convert_gyro(double counts) { -		return counts / counts_per_degsec; +	public static double gyro_degrees_per_second(double counts, double cal) { +		return (counts - cal) * GYRO_FULLSCALE_DEGREES / GYRO_COUNTS;  	}  	public boolean parse_string(String line) { @@ -49,12 +51,12 @@ public class AltosIMU implements Cloneable {  		String[] items = line.split("\\s+");  		if (items.length >= 8) { -			accel_along = Integer.parseInt(items[1]); -			accel_across = Integer.parseInt(items[2]); -			accel_through = Integer.parseInt(items[3]); -			gyro_roll = Integer.parseInt(items[5]); -			gyro_pitch = Integer.parseInt(items[6]); -			gyro_yaw = Integer.parseInt(items[7]); +			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]);  		}  		return true;  	} @@ -62,46 +64,41 @@ public class AltosIMU implements Cloneable {  	public AltosIMU clone() {  		AltosIMU	n = new AltosIMU(); -		n.accel_along = accel_along; -		n.accel_across = accel_across; -		n.accel_through = accel_through; +		n.accel_x = accel_x; +		n.accel_y = accel_y; +		n.accel_z = accel_z; -		n.gyro_roll = gyro_roll; -		n.gyro_pitch = gyro_pitch; -		n.gyro_yaw = gyro_yaw; +		n.gyro_x = gyro_x; +		n.gyro_y = gyro_y; +		n.gyro_z = gyro_z;  		return n;  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try {  			AltosIMU	imu = new AltosIMU(link); - -			if (imu != null) -				state.set_imu(imu); +			AltosCalData	cal_data = listener.cal_data(); + +			if (imu != null) { +				listener.set_gyro(cal_data.gyro_roll(imu.gyro_y), +						  cal_data.gyro_pitch(imu.gyro_x), +						  cal_data.gyro_yaw(imu.gyro_z)); +				listener.set_accel_ground(cal_data.accel_along(imu.accel_y), +							  cal_data.accel_across(imu.accel_x), +							  cal_data.accel_through(imu.accel_z)); +			}  		} catch (TimeoutException te) {  		}  	}  	public AltosIMU() { -		accel_along = AltosLib.MISSING; -		accel_across = AltosLib.MISSING; -		accel_through = AltosLib.MISSING; - -		gyro_roll = AltosLib.MISSING; -		gyro_pitch = AltosLib.MISSING; -		gyro_yaw = AltosLib.MISSING; -	} - -	public AltosIMU(int accel_along, int accel_across, int accel_through, -			int gyro_roll, int gyro_pitch, int gyro_yaw) { - -		this.accel_along = accel_along; -		this.accel_across = accel_across; -		this.accel_through = accel_through; +		accel_x = AltosLib.MISSING; +		accel_y = AltosLib.MISSING; +		accel_z = AltosLib.MISSING; -		this.gyro_roll = gyro_roll; -		this.gyro_pitch = gyro_pitch; -		this.gyro_yaw = gyro_yaw; +		gyro_x = AltosLib.MISSING; +		gyro_y = AltosLib.MISSING; +		gyro_z = AltosLib.MISSING;  	}  	public AltosIMU(AltosLink link) throws InterruptedException, TimeoutException { diff --git a/altoslib/AltosIdle.java b/altoslib/AltosIdle.java index d37af966..b5ee20d0 100644 --- a/altoslib/AltosIdle.java +++ b/altoslib/AltosIdle.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index 73717e17..058df0a1 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; @@ -30,61 +30,62 @@ class AltosIdler {  	static final int	idle_gps = 0;  	static final int	idle_imu = 1;  	static final int	idle_mag = 2; -	static final int	idle_ms5607 = 3;  	static final int	idle_mma655x = 4; +	static final int	idle_ms5607 = 5;  	static final int	idle_sensor_tm = 10;  	static final int	idle_sensor_metrum = 11;  	static final int	idle_sensor_mega = 12; -	static final int	idle_sensor_emini = 13; -	static final int	idle_sensor_tmini2 = 14; -	static final int	idle_sensor_tgps = 15; -	static final int	idle_sensor_tmini3 = 16; +	static final int	idle_sensor_emini1 = 13; +	static final int	idle_sensor_emini2 = 14; +	static final int	idle_sensor_tmini2 = 15; +	static final int	idle_sensor_tgps = 16; +	static final int	idle_sensor_tmini3 = 17; -	public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct { +	public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException, TimeoutException, AltosUnknownProduct {  		for (int idler : idlers) { -			AltosIdle idle = null;  			switch (idler) {  			case idle_gps: -				AltosGPS.update_state(state, link, config_data); +				AltosGPS.provide_data(listener, link);  				break;  			case idle_imu: -				AltosIMU.update_state(state, link, config_data); +				AltosIMU.provide_data(listener, link);  				break;  			case idle_mag: -				AltosMag.update_state(state, link, config_data); -				break; -			case idle_ms5607: -				AltosMs5607.update_state(state, link, config_data); +				AltosMag.provide_data(listener, link);  				break;  			case idle_mma655x: -				AltosMma655x.update_state(state, link, config_data); +				AltosMma655x.provide_data(listener, link); +				break; +			case idle_ms5607: +				AltosMs5607.provide_data(listener, link);  				break;  			case idle_sensor_tm: -				AltosSensorTM.update_state(state, link, config_data); +				AltosSensorTM.provide_data(listener, link);  				break;  			case idle_sensor_metrum: -				AltosSensorMetrum.update_state(state, link, config_data); +				AltosSensorMetrum.provide_data(listener, link);  				break;  			case idle_sensor_mega: -				AltosSensorMega.update_state(state, link, config_data); +				AltosSensorMega.provide_data(listener, link); +				break; +			case idle_sensor_emini1: +				AltosSensorEMini.provide_data(listener, link, 1);  				break; -			case idle_sensor_emini: -				AltosSensorEMini.update_state(state, link, config_data); +			case idle_sensor_emini2: +				AltosSensorEMini.provide_data(listener, link, 2);  				break;  			case idle_sensor_tmini2: -				AltosSensorTMini2.update_state(state, link, config_data); +				AltosSensorTMini2.provide_data(listener, link);  				break;  			case idle_sensor_tgps: -				AltosSensorTGPS.update_state(state, link, config_data); +				AltosSensorTGPS.provide_data(listener, link);  				break;  			case idle_sensor_tmini3: -				AltosSensorTMini3.update_state(state, link, config_data); +				AltosSensorTMini3.provide_data(listener, link);  				break;  			} -			if (idle != null) -				idle.update_state(state);  		}  	} @@ -99,13 +100,17 @@ class AltosIdler {  } -public class AltosIdleFetch implements AltosStateUpdate { +public class AltosIdleFetch implements AltosDataProvider {  	static final AltosIdler[] idlers = { -		new AltosIdler("EasyMini", +		new AltosIdler("EasyMini-v1",  			       AltosIdler.idle_ms5607, -			       AltosIdler.idle_sensor_emini), +			       AltosIdler.idle_sensor_emini1), + +		new AltosIdler("EasyMini-v2", +			       AltosIdler.idle_ms5607, +			       AltosIdler.idle_sensor_emini2),  		new AltosIdler("TeleMini-v1",  			       AltosIdler.idle_sensor_tm), @@ -124,16 +129,19 @@ public class AltosIdleFetch implements AltosStateUpdate {  		new AltosIdler("TeleMetrum-v2",  			       AltosIdler.idle_gps, -			       AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, +			       AltosIdler.idle_mma655x, +			       AltosIdler.idle_ms5607,  			       AltosIdler.idle_sensor_metrum),  		new AltosIdler("TeleMega",  			       AltosIdler.idle_gps, -			       AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, +			       AltosIdler.idle_mma655x, +			       AltosIdler.idle_ms5607,  			       AltosIdler.idle_imu, AltosIdler.idle_mag,  			       AltosIdler.idle_sensor_mega),  		new AltosIdler("EasyMega", -			       AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, +			       AltosIdler.idle_mma655x, +			       AltosIdler.idle_ms5607,  			       AltosIdler.idle_imu, AltosIdler.idle_mag,  			       AltosIdler.idle_sensor_mega),  		new AltosIdler("TeleGPS", @@ -143,29 +151,22 @@ public class AltosIdleFetch implements AltosStateUpdate {  	AltosLink		link; -	public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct { +	public void provide_data(AltosDataListener listener) throws InterruptedException, AltosUnknownProduct {  		try {  			boolean	matched = false;  			/* Fetch config data from remote */  			AltosConfigData config_data = new AltosConfigData(link); -			state.set_state(AltosLib.ao_flight_stateless); -			state.set_serial(config_data.serial); -			state.set_callsign(config_data.callsign); -			state.set_ground_accel(config_data.accel_cal_plus); -			state.set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus); -			state.set_product(config_data.product); -			state.set_firmware_version(config_data.version); -			state.set_log_space(config_data.log_space); +			listener.set_state(AltosLib.ao_flight_stateless);  			for (AltosIdler idler : idlers) {  				if (idler.matches(config_data)) { -					idler.update_state(state, link, config_data); +					idler.provide_data(listener, link);  					matched = true;  					break;  				}  			}  			if (!matched)  				throw new AltosUnknownProduct(config_data.product); -			state.set_received_time(System.currentTimeMillis()); +			listener.set_received_time(System.currentTimeMillis());  		} catch (TimeoutException te) {  		} diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index c374b601..fc5d4cc8 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.concurrent.*; @@ -52,20 +52,20 @@ public class AltosIdleMonitor extends Thread {  		return link.reply_abort;  	} -	boolean update_state(AltosState state) throws InterruptedException, TimeoutException, AltosUnknownProduct { +	boolean provide_data(AltosDataListener listener) throws InterruptedException, TimeoutException, AltosUnknownProduct {  		boolean		worked = false;  		boolean		aborted = false;  		try {  			start_link(); -			fetch.update_state(state); +			fetch.provide_data(listener);  			if (!link.has_error && !link.reply_abort)  				worked = true;  		} finally {  			aborted = stop_link();  			if (worked) {  				if (remote) -					state.set_rssi(link.rssi(), 0); +					listener.set_rssi(link.rssi(), 0);  				listener_state.battery = link.monitor_battery();  			}  		} @@ -92,12 +92,14 @@ public class AltosIdleMonitor extends Thread {  	}  	public void run() { -		AltosState state = new AltosState(); +		AltosState state = null;  		try {  			for (;;) {  				try {  					link.config_data(); -					update_state(state); +					if (state == null) +						state = new AltosState(new AltosCalData(link.config_data())); +					provide_data(state);  					listener.update(state, listener_state);  				} catch (TimeoutException te) {  				} catch (AltosUnknownProduct ae) { diff --git a/altoslib/AltosIdleMonitorListener.java b/altoslib/AltosIdleMonitorListener.java index 3349e9c4..1ddec09a 100644 --- a/altoslib/AltosIdleMonitorListener.java +++ b/altoslib/AltosIdleMonitorListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosIdleMonitorListener {  	public void update(AltosState state, AltosListenerState listener_state); diff --git a/altoslib/AltosIdleReader.java b/altoslib/AltosIdleReader.java index 5903c968..d15e2174 100644 --- a/altoslib/AltosIdleReader.java +++ b/altoslib/AltosIdleReader.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*;  import java.io.*; @@ -25,6 +25,7 @@ import java.util.concurrent.*;  public class AltosIdleReader extends AltosFlightReader {  	AltosLink	link;  	boolean		remote; +	AltosCalData	cal_data = null;  	AltosState	state = null;  	AltosIdleFetch	fetch;  	long		next_millis; @@ -44,15 +45,23 @@ public class AltosIdleReader extends AltosFlightReader {  		return link.reply_abort;  	} +	public AltosCalData cal_data() { +		if (cal_data == null) { +			try { +				cal_data = new AltosCalData(link.config_data()); +			} catch (InterruptedException ie) { +			} catch (TimeoutException te) { +			} +			if (cal_data == null) +				cal_data = new AltosCalData(); +		} +		return cal_data; +	} +  	public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException {  		boolean worked = false;  		boolean aborted = false; -		if (state == null) -			state = new AltosState(); -		else -			state = state.clone(); -  		long	delay = next_millis - System.currentTimeMillis();  		if (delay > 0) @@ -61,7 +70,9 @@ public class AltosIdleReader extends AltosFlightReader {  		try {  			try {  				start_link(); -				fetch.update_state(state); +				if (state == null) +					state = new AltosState(cal_data()); +				fetch.provide_data(state);  				if (!link.has_error && !link.reply_abort)  					worked = true;  			} catch (TimeoutException te) { diff --git a/altoslib/AltosIgnite.java b/altoslib/AltosIgnite.java index cdc5c614..767c00fb 100644 --- a/altoslib/AltosIgnite.java +++ b/altoslib/AltosIgnite.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.*;  import java.io.*; @@ -102,7 +102,7 @@ public class AltosIgnite {  	private void get_npyro() throws InterruptedException, TimeoutException {  		if (config_data == null)  			config_data = new AltosConfigData(link); -		if (config_data != null) +		if (config_data != null && config_data.npyro != AltosLib.MISSING)  			npyro = config_data.npyro;  		else  			npyro = 0; @@ -174,6 +174,7 @@ public class AltosIgnite {  		try {  			start_link();  			link.printf("i DoIt %s\n", igniter); +			link.flush_output();  		} catch (TimeoutException te) {  		} finally {  			stop_link(); diff --git a/altoslib/AltosImage.java b/altoslib/AltosImage.java index 2e32b720..abe9d56f 100644 --- a/altoslib/AltosImage.java +++ b/altoslib/AltosImage.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosJson.java b/altoslib/AltosJson.java index 22f81d03..52c9b41e 100644 --- a/altoslib/AltosJson.java +++ b/altoslib/AltosJson.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; @@ -25,39 +25,39 @@ import java.lang.*;  import java.lang.reflect.*;  class JsonUtil { -	StringBuffer quote(StringBuffer result, String a) { -		result.append("\""); +	Writer quote(Writer writer, String a) throws IOException { +		writer.append("\"");  		for (int i = 0; i < a.length(); i++) {  			char c = a.charAt(i);  			switch (c) {  			case '"':  			case '\\': -				result.append('\\').append(c); +				writer.append('\\').append(c);  				break;  			case '\n': -				result.append("\\n"); +				writer.append("\\n");  				break;  			default: -				result.append(c); +				writer.append(c);  				break;  			}  		} -		result.append("\""); -		return result; +		writer.append("\""); +		return writer;  	} -	StringBuffer append(StringBuffer result, AltosJson value, int indent, boolean pretty) { +	Writer append(Writer result, AltosJson value, int indent, boolean pretty) throws IOException {  		value.append(result, indent, pretty);  		return result;  	} -	StringBuffer append(StringBuffer result, String string) { +	Writer append(Writer result, String string) throws IOException {  		result.append(string);  		return result;  	} -	StringBuffer indent(StringBuffer result, int indent) { +	Writer indent(Writer result, int indent) throws IOException {  		result.append("\n");  		for (int i = 0; i < indent; i++)  			result.append("\t"); @@ -80,7 +80,7 @@ class JsonUtil {  class JsonHash extends JsonUtil {  	Hashtable<String,AltosJson> hash; -	void append_hash(StringBuffer result, int indent, boolean pretty) { +	void append_hash(Writer result, int indent, boolean pretty) throws IOException {  		boolean		first = true;  		result.append("{"); @@ -125,7 +125,7 @@ class JsonHash extends JsonUtil {  class JsonArray extends JsonUtil {  	ArrayList<AltosJson> array; -	void append_array(StringBuffer result, int indent, boolean pretty) { +	void append_array(Writer result, int indent, boolean pretty) throws IOException {  		boolean first = true;  		append(result, "["); @@ -185,6 +185,7 @@ class JsonToken {  	static final int _colon = 9;  	static final int _end = 10;  	static final int _error = 11; +	static final int _none = 12;  	static String token_name(int token) {  		switch (token) { @@ -245,7 +246,7 @@ class JsonToken {  		this.sval = sval;  	} -	JsonToken(int token, StringBuffer bval) { +	JsonToken(int token, Writer bval) {  		this(token, bval.toString());  	}  } @@ -254,11 +255,11 @@ class JsonToken {   * Lexer for json   */  class JsonLexer extends JsonUtil { -	StringReader	f; -	int		line; -	int		ungot = -2; -	StringBuffer	pending_token; -	JsonToken	token; +	InputStream		f; +	int			line; +	int			ungot = -2; +	StringBuffer		pending_token; +	private JsonToken	token;  	static class keyword {  		String		word; @@ -382,7 +383,7 @@ class JsonLexer extends JsonUtil {  						return new JsonToken(JsonToken._long, lval);  					}  				case '"': -					StringBuffer bval = new StringBuffer(); +					Writer bval = new StringWriter();  					for (;;) {  						c = ch();  						if (c == '"') @@ -400,7 +401,7 @@ class JsonLexer extends JsonUtil {  								break;  							}  						} -						bval.appendCodePoint(c); +						bval.write(c);  					}  					return new JsonToken(JsonToken._string, bval);  				default: @@ -424,11 +425,17 @@ class JsonLexer extends JsonUtil {  	}  	void next() { -		token = lex(); +		token = null; +	} + +	JsonToken token() { +		if (token == null) +			token = lex(); +		return token;  	}  	JsonToken expect(int e) { -		JsonToken t = token; +		JsonToken t = token();  		if (t.token != e)  			throw new IllegalArgumentException(String.format("got \"%s\" while expecting \"%s\"",  									 token.token_name(), @@ -438,7 +445,13 @@ class JsonLexer extends JsonUtil {  	}  	JsonLexer(String s) { -		f = new StringReader(s); +		f = new AltosStringInputStream(s); +		line = 1; +		token = null; +	} + +	JsonLexer(InputStream f) { +		this.f = f;  		line = 1;  		token = null;  	} @@ -464,7 +477,7 @@ class JsonParse {  		lexer.next();  		for (;;) {  			/* Allow for empty hashes */ -			if (lexer.token.token == JsonToken._cc) { +			if (lexer.token().token == JsonToken._cc) {  				lexer.next();  				return hash;  			} @@ -475,7 +488,7 @@ class JsonParse {  			AltosJson value = value();  			hash.put(key, value); -			switch (lexer.token.token) { +			switch (lexer.token().token) {  			case JsonToken._comma:  				lexer.next();  				break; @@ -483,7 +496,7 @@ class JsonParse {  				lexer.next();  				return hash;  			default: -				parse_error("got %s expect \",\" or \"}\"", lexer.token.token_name()); +				parse_error("got %s expect \",\" or \"}\"", lexer.token().token_name());  				return null;  			}  		} @@ -496,14 +509,14 @@ class JsonParse {  		lexer.next();  		for (int i = 0;; i++) {  			/* Allow for empty arrays */ -			if (lexer.token.token == JsonToken._cs) { +			if (lexer.token().token == JsonToken._cs) {  				lexer.next();  				return array;  			}  			AltosJson value = value();  			array.put(i, value); -			switch (lexer.token.token) { +			switch (lexer.token().token) {  			case JsonToken._comma:  				lexer.next();  				break; @@ -511,7 +524,7 @@ class JsonParse {  				lexer.next();  				return array;  			default: -				parse_error("got %s expect \",\" or \"]\"", lexer.token.token_name()); +				parse_error("got %s expect \",\" or \"]\"", lexer.token().token_name());  				return null;  			}  		} @@ -521,29 +534,29 @@ class JsonParse {  	 * identify the next object in the input  	 */  	AltosJson value() { -		switch (lexer.token.token) { +		switch (lexer.token().token) {  		case JsonToken._oc:  			return new AltosJson(hash());  		case JsonToken._os:  			return new AltosJson(array());  		case JsonToken._double: -			double dval = lexer.token.dval; +			double dval = lexer.token().dval;  			lexer.next();  			return new AltosJson(dval);  		case JsonToken._long: -			long lval = lexer.token.lval; +			long lval = lexer.token().lval;  			lexer.next();  			return new AltosJson(lval);  		case JsonToken._string: -			String sval = lexer.token.sval; +			String sval = lexer.token().sval;  			lexer.next();  			return new AltosJson(sval);  		case JsonToken._boolean: -			boolean bval = lexer.token.bval; +			boolean bval = lexer.token().bval;  			lexer.next();  			return new AltosJson(bval);  		default: -			parse_error("Unexpected token \"%s\"", lexer.token.token_name()); +			parse_error("Unexpected token \"%s\"", lexer.token().token_name());  		}  		return null;  	} @@ -556,6 +569,10 @@ class JsonParse {  	JsonParse(String s) {  		lexer = new JsonLexer(s);  	} + +	JsonParse(InputStream f) { +		lexer = new JsonLexer(f); +	}  }  public class AltosJson extends JsonUtil { @@ -578,7 +595,7 @@ public class AltosJson extends JsonUtil {  	/* Generate string representation of the value  	 */ -	StringBuffer append(StringBuffer result, int indent, boolean pretty) { +	Writer append(Writer result, int indent, boolean pretty) throws IOException {  		switch (type) {  		case type_hash:  			hash.append_hash(result, indent, pretty); @@ -615,9 +632,13 @@ public class AltosJson extends JsonUtil {  	}  	private String toString(int indent, boolean pretty) { -		StringBuffer result = new StringBuffer(); -		append(result, indent, pretty); -		return result.toString(); +		try { +			Writer result = new StringWriter(); +			append(result, indent, pretty); +			return result.toString(); +		} catch (Exception e) { +			return null; +		}  	}  	public String toString() { @@ -628,6 +649,14 @@ public class AltosJson extends JsonUtil {  		return toString(0, true);  	} +	public void write(Writer w, int indent, boolean pretty) throws IOException { +		append(w, indent, pretty); +	} + +	public void write(Writer w) throws IOException { +		write(w, 0, true); +	} +  	/* Parse string representation to a value  	 */ @@ -641,6 +670,16 @@ public class AltosJson extends JsonUtil {  		}  	} +	public static AltosJson fromInputStream(InputStream f) { +		JsonParse	parse = new JsonParse(f); +		try { +			return parse.parse(); +		} catch (IllegalArgumentException ie) { +			System.out.printf("json:\n%s\n", ie.getMessage()); +			return null; +		} +	} +  	/* Accessor functions  	 */  	private boolean assert_type(boolean setting, int type, int other_type, String error) { @@ -1213,6 +1252,10 @@ public class AltosJson extends JsonUtil {  				for (Field field : c.getDeclaredFields()) {  					String	fieldName = field.getName(); +					/* XXX hack to allow fields to be not converted */ +					if (fieldName.startsWith("__")) +						continue; +  					/* Skip static fields */  					if (Modifier.isStatic(field.getModifiers()))  						continue; diff --git a/altoslib/AltosKML.java b/altoslib/AltosKML.java index 25108bf9..587b845b 100644 --- a/altoslib/AltosKML.java +++ b/altoslib/AltosKML.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; @@ -36,8 +36,9 @@ public class AltosKML implements AltosWriter {  	File			name;  	PrintWriter		out;  	int			flight_state = -1; -	AltosState		prev = null; -	double			gps_start_altitude; +	AltosGPS		prev = null; +	double			gps_start_altitude = AltosLib.MISSING; +	AltosFlightStats	stats;  	static final String[] kml_state_colors = {  		"FF000000",	// startup @@ -101,42 +102,47 @@ public class AltosKML implements AltosWriter {  		"</Document>\n" +  		"</kml>\n"; -	void start (AltosState record) { -		out.printf(kml_header_start, record.flight, record.serial); +	void start (AltosCalData cal_data) { +		AltosGPS gps = cal_data.gps_pad; + +		gps_start_altitude = cal_data.gps_pad_altitude; +		out.printf(kml_header_start, cal_data.flight, cal_data.serial);  		out.printf("Date:   %04d-%02d-%02d\n", -			   record.gps.year, record.gps.month, record.gps.day); +			   gps.year, gps.month, gps.day);  		out.printf("Time:     %2d:%02d:%02d\n", -			   record.gps.hour, record.gps.minute, record.gps.second); +			   gps.hour, gps.minute, gps.second);  		out.printf("%s", kml_header_end);  	}  	boolean	started = false; -	void state_start(AltosState state) { -		String	state_name = AltosLib.state_name(state.state()); -		String	state_color = state_color(state.state()); +	void state_start(int state) { +		String	state_name = AltosLib.state_name(state); +		String	state_color = state_color(state);  		out.printf(kml_style_start, state_name, state_color); -		out.printf("\tState: %s\n", state_name); +		out.printf("State: %s\n", state_name); +		out.printf("Time: %6.2f s\n", stats.state_time[state]); +		out.printf("Average speed: %s\n", AltosConvert.speed.show(6, stats.state_speed[state])); +		out.printf("Average accel: %s\n", AltosConvert.accel.show(6, stats.state_accel[state]));  		out.printf("%s", kml_style_end);  		out.printf(kml_placemark_start, state_name, state_name);  	} -	void state_end(AltosState state) { +	void state_end() {  		out.printf("%s", kml_placemark_end);  	} -	void coord(AltosState state) { -		AltosGPS	gps = state.gps; +	void coord(double time, AltosGPS gps, int state, double height) {  		double		altitude; -		if (state.height() != AltosLib.MISSING) -			altitude = state.height() + gps_start_altitude; +		if (height != AltosLib.MISSING) +			altitude = height + gps_start_altitude;  		else  			altitude = gps.alt;  		out.printf(kml_coord_fmt,  			   gps.lon, gps.lat,  			   altitude, (double) gps.alt, -			   state.time, gps.nsat); +			   time, gps.nsat);  	}  	void end() { @@ -145,7 +151,7 @@ public class AltosKML implements AltosWriter {  	public void close() {  		if (prev != null) { -			state_end(prev); +			state_end();  			end();  			prev = null;  		} @@ -155,40 +161,37 @@ public class AltosKML implements AltosWriter {  		}  	} -	public void write(AltosState state) { -		AltosGPS	gps = state.gps; - -		if (gps == null) -			return; - +	public void write(AltosGPSTimeValue gtv, AltosCalData cal_data, int state, double height) { +		AltosGPS gps = gtv.gps;  		if (gps.lat == AltosLib.MISSING)  			return;  		if (gps.lon == AltosLib.MISSING)  			return; -		if (!started) { -			start(state); -			started = true; -			gps_start_altitude = gps.alt; -		} -		if (prev != null && prev.gps_sequence == state.gps_sequence) -			return; -		if (state.state() != flight_state) { -			flight_state = state.state(); +		if (state != flight_state) { +			flight_state = state;  			if (prev != null) { -				coord(state); -				state_end(prev); +				coord(gtv.time, gps, state, height); +				state_end();  			}  			state_start(state);  		} -		coord(state); -		prev = state; +		coord(0, gps, state, height); +		prev = gps;  	} -	public void write(AltosStateIterable states) { -		for (AltosState state : states) { -			if ((state.set & AltosState.set_gps) != 0) -				write(state); -		} +	private int state(AltosFlightSeries series, double time) { +		return (int) series.value_before(AltosFlightSeries.state_name, time); +	} + +	private double height(AltosFlightSeries series, double time) { +		return series.value(AltosFlightSeries.height_name, time); +	} + +	public void write(AltosFlightSeries series) { +		stats = new AltosFlightStats(series); +		start(series.cal_data()); +		for (AltosGPSTimeValue gtv : series.gps_series) +			write(gtv, series.cal_data(), state(series, gtv.time), height(series, gtv.time));  	}  	public AltosKML(File in_name) throws FileNotFoundException { diff --git a/altoslib/AltosLatLon.java b/altoslib/AltosLatLon.java index 5865d3cc..6fcc43fe 100644 --- a/altoslib/AltosLatLon.java +++ b/altoslib/AltosLatLon.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosLatLon {  	public double	lat; diff --git a/altoslib/AltosLatitude.java b/altoslib/AltosLatitude.java index 4663cd09..f43397d0 100644 --- a/altoslib/AltosLatitude.java +++ b/altoslib/AltosLatitude.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosLatitude extends AltosLocation {  	public String pos() { return "N"; } diff --git a/altoslib/AltosLaunchSite.java b/altoslib/AltosLaunchSite.java index 8a06cdb2..19fb4858 100644 --- a/altoslib/AltosLaunchSite.java +++ b/altoslib/AltosLaunchSite.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.lang.*; diff --git a/altoslib/AltosLaunchSiteListener.java b/altoslib/AltosLaunchSiteListener.java index d2ee601e..0d926353 100644 --- a/altoslib/AltosLaunchSiteListener.java +++ b/altoslib/AltosLaunchSiteListener.java @@ -15,7 +15,7 @@   * with this program; if not, write to the Free Software Foundation, Inc.,   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.lang.*; diff --git a/altoslib/AltosLaunchSites.java b/altoslib/AltosLaunchSites.java index d5c41c82..365f19e3 100644 --- a/altoslib/AltosLaunchSites.java +++ b/altoslib/AltosLaunchSites.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.lang.*; diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index a3f164d4..d1063509 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.*;  import java.io.*; @@ -38,6 +38,20 @@ public class AltosLib {  	public static final int AO_LOG_GPS_DATE = 'Y';  	public static final int AO_LOG_PRESSURE = 'P'; +	public static boolean is_gps_cmd(int cmd) { +		switch (cmd) { +		case AltosLib.AO_LOG_GPS_POS: +		case AltosLib.AO_LOG_GPS_TIME: +		case AltosLib.AO_LOG_GPS_LAT: +		case AltosLib.AO_LOG_GPS_LON: +		case AltosLib.AO_LOG_GPS_ALT: +		case AltosLib.AO_LOG_GPS_SAT: +		case AltosLib.AO_LOG_GPS_DATE: +			return true; +		} +		return false; +	} +  	/* 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; @@ -162,6 +176,16 @@ public class AltosLib {  		return product_any;  	} +	public static boolean has_9dof(int device_type) { +		return device_type == product_telemega || device_type == product_easymega; +	} + +	public static boolean has_gps(int device_type) { +		return device_type == product_telemetrum || +			device_type == product_telemega || +			device_type == product_telegps; +	} +  	/* Bluetooth "identifier" (bluetooth sucks) */  	public final static String bt_product_telebt = "TeleBT"; @@ -330,7 +354,7 @@ public class AltosLib {  	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_TELEMEGA_OLD = 5; -	public static final int AO_LOG_FORMAT_EASYMINI = 6; +	public static final int AO_LOG_FORMAT_EASYMINI1 = 6;  	public static final int AO_LOG_FORMAT_TELEMETRUM = 7;  	public static final int AO_LOG_FORMAT_TELEMINI2 = 8;  	public static final int AO_LOG_FORMAT_TELEGPS = 9; @@ -338,6 +362,7 @@ public class AltosLib {  	public static final int AO_LOG_FORMAT_DETHERM = 11;  	public static final int AO_LOG_FORMAT_TELEMINI3 = 12;  	public static final int AO_LOG_FORMAT_TELEFIRETWO = 13; +	public static final int AO_LOG_FORMAT_EASYMINI2 = 14;  	public static final int AO_LOG_FORMAT_NONE = 127;  	public static boolean isspace(int c) { @@ -561,7 +586,31 @@ public class AltosLib {  		}  	} -	public static String ignitor_name(int i) { +	public static String igniter_name(int i) {  		return String.format("Ignitor %c", 'A' + i);  	} + +	public static AltosRecordSet record_set(File file) throws FileNotFoundException, IOException { +		FileInputStream in; +		in = new FileInputStream(file); +		if (file.getName().endsWith("telem")) { +			return new AltosTelemetryFile(in); +		} else if (file.getName().endsWith("eeprom")) { +			return new AltosEepromFile(in); +		} else { +			String	name = file.getName(); +			int	dot = name.lastIndexOf('.'); +			String	extension; + +			if (dot == -1) +				throw new IOException(String.format("%s (Missing extension)", file.toString())); +			else { +				extension = name.substring(dot); +				throw new IOException(String.format("%s (Invalid extension '%s')", +								    file.toString(), +								    extension)); +			} +		} +	} +  } diff --git a/altoslib/AltosLine.java b/altoslib/AltosLine.java index 952a21e3..b3833f64 100644 --- a/altoslib/AltosLine.java +++ b/altoslib/AltosLine.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosLine {  	public String	line; diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 76a4eb31..5a802ef1 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.concurrent.*; @@ -556,7 +556,7 @@ public abstract class AltosLink implements Runnable {  			return AltosLib.MISSING;  		double	volts = AltosLib.MISSING; -		if (config_data.product.startsWith("TeleBT-v3")) { +		if (config_data.product.startsWith("TeleBT-v3") || config_data.product.startsWith("TeleBT-v4")) {  			volts = AltosConvert.tele_bt_3_battery(monitor_batt);  		} else {  			volts = AltosConvert.cc_battery_to_voltage(monitor_batt); diff --git a/altoslib/AltosListenerState.java b/altoslib/AltosListenerState.java index 80bc0df2..949d2271 100644 --- a/altoslib/AltosListenerState.java +++ b/altoslib/AltosListenerState.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosLocation.java b/altoslib/AltosLocation.java index c612caaa..45831004 100644 --- a/altoslib/AltosLocation.java +++ b/altoslib/AltosLocation.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public abstract class AltosLocation extends AltosUnits { diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java index 6d873d78..44bea646 100644 --- a/altoslib/AltosLog.java +++ b/altoslib/AltosLog.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.text.*; @@ -61,8 +61,8 @@ public class AltosLog implements Runnable {  		return file;  	} -	boolean open (AltosState state) throws IOException, InterruptedException { -		AltosFile	a = new AltosFile(state); +	boolean open (AltosCalData cal_data) throws IOException, InterruptedException { +		AltosFile	a = new AltosFile(cal_data);  		log_file = new FileWriter(a, true);  		if (log_file != null) { @@ -80,24 +80,31 @@ public class AltosLog implements Runnable {  	public void run () {  		try { -			AltosState	state = new AltosState();  			AltosConfigData	receiver_config = link.config_data(); -			state.set_receiver_serial(receiver_config.serial); +			AltosCalData	cal_data = new AltosCalData(); +			AltosState	state = null; +			cal_data.set_receiver_serial(receiver_config.serial);  			for (;;) {  				AltosLine	line = input_queue.take();  				if (line.line == null)  					continue;  				try {  					AltosTelemetry	telem = AltosTelemetry.parse(line.line); -					state = state.clone(); -					telem.update_state(state); -					if (state.serial != serial || state.flight != flight || log_file == null) +					if (state == null) +						state = new AltosState(cal_data); +					telem.provide_data(state); + +					if (cal_data.serial != serial || +					    cal_data.flight != flight || +					    log_file == null)  					{  						close_log_file(); -						serial = state.serial; -						flight = state.flight; -						if (state.serial != AltosLib.MISSING && state.flight != AltosLib.MISSING) -							open(state); +						serial = cal_data.serial; +						flight = cal_data.flight; +						state = null; +						if (cal_data.serial != AltosLib.MISSING && +						    cal_data.flight != AltosLib.MISSING) +							open(cal_data);  					}  				} catch (ParseException pe) {  				} catch (AltosCRCException ce) { diff --git a/altoslib/AltosLongitude.java b/altoslib/AltosLongitude.java index 4c6d1857..b2134cbb 100644 --- a/altoslib/AltosLongitude.java +++ b/altoslib/AltosLongitude.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosLongitude extends AltosLocation {  	public String pos() { return "E"; } diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java index e89ec0de..0d8ec69f 100644 --- a/altoslib/AltosMag.java +++ b/altoslib/AltosMag.java @@ -16,15 +16,15 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.*;  import java.io.*;  public class AltosMag implements Cloneable { -	public int		along; -	public int		across; -	public int		through; +	public int		x; +	public int		z; +	public int		y;  	public static final double counts_per_gauss = 1090; @@ -33,10 +33,6 @@ public class AltosMag implements Cloneable {  	}  	public boolean parse_string(String line) { -//		if (line.startsWith("Syntax error")) { -//			along = across = through = 0; -//			return true; -//		}  		if (!line.startsWith("X:"))  			return false; @@ -44,9 +40,9 @@ public class AltosMag implements Cloneable {  		String[] items = line.split("\\s+");  		if (items.length >= 6) { -			along = Integer.parseInt(items[1]); -			across = Integer.parseInt(items[3]); -			through = Integer.parseInt(items[5]); +			x = Integer.parseInt(items[1]); +			z = Integer.parseInt(items[3]); +			y = Integer.parseInt(items[5]);  		}  		return true;  	} @@ -54,30 +50,27 @@ public class AltosMag implements Cloneable {  	public AltosMag clone() {  		AltosMag n = new AltosMag(); -		n.along = along; -		n.across = across; -		n.through = through; +		n.x = x; +		n.z = z; +		n.y = y;  		return n;  	}  	public AltosMag() { -		along = AltosLib.MISSING; -		across = AltosLib.MISSING; -		through = AltosLib.MISSING; +		x = AltosLib.MISSING; +		z = AltosLib.MISSING; +		y = AltosLib.MISSING;  	} -	public AltosMag(int along, int across, int through) { -		this.along = along; -		this.across = across; -		this.through = through; -	} - -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try {  			AltosMag	mag = new AltosMag(link); +			AltosCalData	cal_data = listener.cal_data();  			if (mag != null) -				state.set_mag(mag); +				listener.set_mag(cal_data.mag_along(mag.y), +						 cal_data.mag_across(mag.x), +						 cal_data.mag_through(mag.z));  		} catch (TimeoutException te) {  		}  	} diff --git a/altoslib/AltosMap.java b/altoslib/AltosMap.java index e3c4a6a7..286cf1bb 100644 --- a/altoslib/AltosMap.java +++ b/altoslib/AltosMap.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.lang.*; @@ -220,11 +220,11 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {  		return false;  	} -	public void show(AltosState state, AltosListenerState listener_state) { +	public void show(AltosGPS gps, int state) { -		/* If insufficient gps data, nothing to update +		/* +		 * If insufficient gps data, nothing to update  		 */ -		AltosGPS	gps = state.gps;  		if (gps == null)  			return; @@ -232,23 +232,23 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {  		if (!gps.locked && gps.nsat < 4)  			return; -		switch (state.state()) { +		switch (state) {  		case AltosLib.ao_flight_boost:  			if (!have_boost) { -				add_mark(gps.lat, gps.lon, state.state()); +				add_mark(gps.lat, gps.lon, state);  				have_boost = true;  			}  			break;  		case AltosLib.ao_flight_landed:  			if (!have_landed) { -				add_mark(gps.lat, gps.lon, state.state()); +				add_mark(gps.lat, gps.lon, state);  				have_landed = true;  			}  			break;  		}  		if (path != null) { -			AltosMapRectangle	damage = path.add(gps.lat, gps.lon, state.state()); +			AltosMapRectangle	damage = path.add(gps.lat, gps.lon, state);  			if (damage != null)  				repaint(damage, AltosMapPath.stroke_width); @@ -259,6 +259,10 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {  		maybe_centre(gps.lat, gps.lon);  	} +	public void show(AltosState state, AltosListenerState listener_state) { +		show(state.gps, state.state()); +	} +  	public void centre(AltosLatLon lat_lon) {  		centre = lat_lon;  		set_transform(); @@ -268,10 +272,14 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {  		centre(new AltosLatLon(lat, lon));  	} -	public void centre(AltosState state) { -		if (!state.gps.locked && state.gps.nsat < 4) +	public void centre(AltosGPS gps) { +		if (!gps.locked && gps.nsat < 4)  			return; -		centre(state.gps.lat, state.gps.lon); +		centre(gps.lat, gps.lon); +	} + +	public void centre(AltosState state) { +		centre(state.gps);  	}  	public void maybe_centre(double lat, double lon) { diff --git a/altoslib/AltosMapCache.java b/altoslib/AltosMapCache.java index 4e529177..54d2dbdd 100644 --- a/altoslib/AltosMapCache.java +++ b/altoslib/AltosMapCache.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.net.*; diff --git a/altoslib/AltosMapCacheListener.java b/altoslib/AltosMapCacheListener.java index 057d1c43..8c07e3c1 100644 --- a/altoslib/AltosMapCacheListener.java +++ b/altoslib/AltosMapCacheListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosMapCacheListener {  	public void map_cache_changed(int map_cache); diff --git a/altoslib/AltosMapInterface.java b/altoslib/AltosMapInterface.java index a2ea81db..5089db64 100644 --- a/altoslib/AltosMapInterface.java +++ b/altoslib/AltosMapInterface.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.net.*; diff --git a/altoslib/AltosMapLine.java b/altoslib/AltosMapLine.java index c475f52d..f2174935 100644 --- a/altoslib/AltosMapLine.java +++ b/altoslib/AltosMapLine.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.lang.Math; @@ -44,39 +44,9 @@ public abstract class AltosMapLine {  	}  	public String line_dist() { -		String	format;  		AltosGreatCircle	g = new AltosGreatCircle(start.lat, start.lon,  								 end.lat, end.lon); -		double	distance = g.distance; -		if (AltosConvert.imperial_units) { -			distance = AltosConvert.meters_to_feet(distance); -			if (distance < 1000) { -				format = "%4.0fft"; -			} else { -				distance /= 5280; -				if (distance < 10) -					format = "%5.3fmi"; -				else if (distance < 100) -					format = "%5.2fmi"; -				else if (distance < 1000) -					format = "%5.1fmi"; -				else -					format = "%5.0fmi"; -			} -		} else { -			if (distance < 1000) { -				format = "%4.0fm"; -			} else { -				distance /= 1000; -				if (distance < 100) -					format = "%5.2fkm"; -				else if (distance < 1000) -					format = "%5.1fkm"; -				else -					format = "%5.0fkm"; -			} -		} -		return String.format(format, distance); +		return AltosConvert.distance.show(7, g.distance);  	}  } diff --git a/altoslib/AltosMapLoader.java b/altoslib/AltosMapLoader.java index 17e88bf4..b57591df 100644 --- a/altoslib/AltosMapLoader.java +++ b/altoslib/AltosMapLoader.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; diff --git a/altoslib/AltosMapLoaderListener.java b/altoslib/AltosMapLoaderListener.java index 07624f80..7f36c002 100644 --- a/altoslib/AltosMapLoaderListener.java +++ b/altoslib/AltosMapLoaderListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosMapLoaderListener {  	public abstract void loader_start(int max); diff --git a/altoslib/AltosMapMark.java b/altoslib/AltosMapMark.java index cbe7bebe..4ef179ef 100644 --- a/altoslib/AltosMapMark.java +++ b/altoslib/AltosMapMark.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.lang.Math; diff --git a/altoslib/AltosMapPath.java b/altoslib/AltosMapPath.java index c2335169..1542a4e9 100644 --- a/altoslib/AltosMapPath.java +++ b/altoslib/AltosMapPath.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.lang.Math; diff --git a/altoslib/AltosMapPathPoint.java b/altoslib/AltosMapPathPoint.java index 5182ecfd..409a6a5c 100644 --- a/altoslib/AltosMapPathPoint.java +++ b/altoslib/AltosMapPathPoint.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.lang.Math; diff --git a/altoslib/AltosMapRectangle.java b/altoslib/AltosMapRectangle.java index a2321e19..0751aa33 100644 --- a/altoslib/AltosMapRectangle.java +++ b/altoslib/AltosMapRectangle.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosMapRectangle {  	AltosLatLon	ul, lr; diff --git a/altoslib/AltosMapStore.java b/altoslib/AltosMapStore.java index 7cce05a5..4eba3a04 100644 --- a/altoslib/AltosMapStore.java +++ b/altoslib/AltosMapStore.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.net.*; @@ -91,6 +91,7 @@ public class AltosMapStore {  	static Object	forbidden_lock = new Object();  	static long	forbidden_time;  	static boolean	forbidden_set; +	public static int forbidden_response;  	private int fetch_url() {  		URL u; @@ -116,6 +117,7 @@ public class AltosMapStore {  					synchronized (forbidden_lock) {  						forbidden_time = System.nanoTime();  						forbidden_set = true; +						forbidden_response = response;  						return AltosMapTile.forbidden;  					}  				} diff --git a/altoslib/AltosMapStoreListener.java b/altoslib/AltosMapStoreListener.java index e3935201..1fb7194a 100644 --- a/altoslib/AltosMapStoreListener.java +++ b/altoslib/AltosMapStoreListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosMapStoreListener {  	abstract void notify_store(AltosMapStore store, int status); diff --git a/altoslib/AltosMapTile.java b/altoslib/AltosMapTile.java index 4d6dc8d1..4b01e437 100644 --- a/altoslib/AltosMapTile.java +++ b/altoslib/AltosMapTile.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; diff --git a/altoslib/AltosMapTileListener.java b/altoslib/AltosMapTileListener.java index 219dcd07..3c6275a0 100644 --- a/altoslib/AltosMapTileListener.java +++ b/altoslib/AltosMapTileListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosMapTileListener {  	abstract public void notify_tile(AltosMapTile tile, int status); diff --git a/altoslib/AltosMapTransform.java b/altoslib/AltosMapTransform.java index 266557b6..b6d4f435 100644 --- a/altoslib/AltosMapTransform.java +++ b/altoslib/AltosMapTransform.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.lang.Math; diff --git a/altoslib/AltosMapTypeListener.java b/altoslib/AltosMapTypeListener.java index 1d5e2b47..94401a00 100644 --- a/altoslib/AltosMapTypeListener.java +++ b/altoslib/AltosMapTypeListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosMapTypeListener {  	public void map_type_changed(int map_type); diff --git a/altoslib/AltosMapZoomListener.java b/altoslib/AltosMapZoomListener.java index 93c26cbb..c4a0acd6 100644 --- a/altoslib/AltosMapZoomListener.java +++ b/altoslib/AltosMapZoomListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosMapZoomListener {  	abstract public void zoom_changed(int zoom); diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java index 503eb5fd..0f6022ac 100644 --- a/altoslib/AltosMma655x.java +++ b/altoslib/AltosMma655x.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.*; @@ -46,17 +46,18 @@ public class AltosMma655x implements Cloneable {  		return n;  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, AltosUnknownProduct { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException, AltosUnknownProduct {  		try {  			AltosMma655x	mma655x = new AltosMma655x(link); +			AltosCalData	cal_data = listener.cal_data();  			if (mma655x != null) {  				int accel = mma655x.accel; -				if (config_data.mma655x_inverted()) +				if (cal_data.mma655x_inverted)  					accel = 4095 - accel; -				if (config_data.pad_orientation == 1) +				if (cal_data.pad_orientation == 1)  					accel = 4095 - accel; -				state.set_accel(accel); +				listener.set_acceleration(cal_data.acceleration(accel));  			}  		} catch (TimeoutException te) {  		} catch (NumberFormatException ne) { diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java index 631bc716..5b3ba65d 100644 --- a/altoslib/AltosMs5607.java +++ b/altoslib/AltosMs5607.java @@ -16,34 +16,42 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.*;  import java.io.*;  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; - -	static final boolean	ms5611 = false; - -	void convert() { +	public int	reserved = AltosLib.MISSING; +	public int	sens = AltosLib.MISSING; +	public int	off = AltosLib.MISSING; +	public int	tcs = AltosLib.MISSING; +	public int	tco = AltosLib.MISSING; +	public int	tref = AltosLib.MISSING; +	public int	tempsens = AltosLib.MISSING; +	public int	crc = AltosLib.MISSING; +	private boolean	ms5611 = false; + +	public boolean valid_config() { +		return reserved != AltosLib.MISSING && +			sens != AltosLib.MISSING && +			off != AltosLib.MISSING && +			tcs != AltosLib.MISSING && +			tco != AltosLib.MISSING && +			tref != AltosLib.MISSING && +			tempsens != AltosLib.MISSING && +			crc  != AltosLib.MISSING; +	} + +	public AltosPresTemp pres_temp(int raw_pres, int raw_temp) {  		int	dT; -		int TEMP; -		long OFF; -		long SENS; -		//int P; +		int	TEMP; +		long	OFF; +		long	SENS; +		int	P; + +		if (raw_pres == AltosLib.MISSING || raw_temp == AltosLib.MISSING) +			return new AltosPresTemp(AltosLib.MISSING, AltosLib.MISSING);  		dT = raw_temp - ((int) tref << 8); @@ -64,7 +72,7 @@ public class AltosMs5607 {  			int TEMPM = TEMP - 2000;  			long OFF2 = ((long) 61 * (long) TEMPM * (long) TEMPM) >> 4;  			long SENS2 = (long) 2 * (long) TEMPM * (long) TEMPM; -			if (TEMP < 1500) { +			if (TEMP < -1500) {  				int TEMPP = TEMP + 1500;  				long TEMPP2 = (long) TEMPP * (long) TEMPP;  				OFF2 = OFF2 + 15 * TEMPP2; @@ -75,96 +83,75 @@ public class AltosMs5607 {  			SENS -= SENS2;  		} -		pa = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); -		cc = TEMP; -	} +		P = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); -	public int set(int in_pres, int in_temp) { -		raw_pres = in_pres; -		raw_temp = in_temp; -		convert(); -		return pa; +		return new AltosPresTemp(P, TEMP / 100.0);  	} -	public boolean parse_line(String line) { -		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]); +	public AltosPresTemp pres_temp(AltosLink link) throws InterruptedException, TimeoutException { +		int	raw_pres = AltosLib.MISSING; +		int	raw_temp = AltosLib.MISSING; +		boolean	done = false; + +		link.printf("B\n"); +		while (!done) { +			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("Altitude:")) { +				done = true;  			} -		} 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:")) { -			return false;  		} -		return true; +		return pres_temp(raw_pres, raw_temp); +	} + +	public AltosMs5607(boolean ms5611) { +		this.ms5611 = ms5611;  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	public AltosMs5607() { +		this(false); +	} + +	public AltosMs5607(AltosMs5607 old) { +		reserved = old.reserved; +		sens = old.sens; +		off = old.off; +		tcs = old.tcs; +		tco = old.tco; +		tref = old.tref; +		tempsens = old.tempsens; +		crc = old.crc; +	} + +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try { -			AltosMs5607	ms5607 = new AltosMs5607(link, config_data); +			AltosCalData	cal_data = listener.cal_data(); +			AltosMs5607	ms5607 = cal_data.ms5607;  			if (ms5607 != null) { -				state.set_ms5607(ms5607); -				return; +				AltosPresTemp	pt = ms5607.pres_temp(link); +				listener.set_temperature(pt.temp); +				listener.set_pressure(pt.pres);  			}  		} catch (TimeoutException te) {  		}  	} -	public AltosMs5607() { -		raw_pres = AltosLib.MISSING; -		raw_temp = AltosLib.MISSING; -		pa = AltosLib.MISSING; -		cc = AltosLib.MISSING; +	public AltosMs5607(AltosConfigData config_data) { +		this(config_data.ms5607());  	}  	public AltosMs5607 (AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException { -		this(); -		reserved = config_data.ms5607_reserved; -		sens = config_data.ms5607_sens; -		off = config_data.ms5607_off; -		tcs = config_data.ms5607_tcs; -		tco = config_data.ms5607_tco; -		tref = config_data.ms5607_tref; -		tempsens = config_data.ms5607_tempsens; -		crc = config_data.ms5607_crc; -		link.printf("B\n"); -		for (;;) { -			String line = link.get_reply_no_dialog(5000); -			if (line == null) { -				throw new TimeoutException(); -			} -			if (!parse_line(line)) { -				break; -			} -		} -		convert(); +		this(config_data);  	}  } diff --git a/altoslib/AltosNoSymbol.java b/altoslib/AltosNoSymbol.java index 37542cf0..8372d396 100644 --- a/altoslib/AltosNoSymbol.java +++ b/altoslib/AltosNoSymbol.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosNoSymbol extends Exception {  	public AltosNoSymbol(String name) { diff --git a/altoslib/AltosOrient.java b/altoslib/AltosOrient.java index 8b3a3541..4546a798 100644 --- a/altoslib/AltosOrient.java +++ b/altoslib/AltosOrient.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosOrient extends AltosUnits { diff --git a/altoslib/AltosParse.java b/altoslib/AltosParse.java index b4b6f875..77cf969d 100644 --- a/altoslib/AltosParse.java +++ b/altoslib/AltosParse.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.*;  import java.text.*; diff --git a/altoslib/AltosPointDouble.java b/altoslib/AltosPointDouble.java index 31b03b1f..301d07b0 100644 --- a/altoslib/AltosPointDouble.java +++ b/altoslib/AltosPointDouble.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosPointDouble {  	public double	x, y; diff --git a/altoslib/AltosPointInt.java b/altoslib/AltosPointInt.java index 233a8d31..25f5dd2a 100644 --- a/altoslib/AltosPointInt.java +++ b/altoslib/AltosPointInt.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosPointInt {  	public int	x, y; diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 35d44631..0c388f1b 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; @@ -363,11 +363,11 @@ public class AltosPreferences {  		}  	} -	public static void set_state(AltosState state) { +	public static void set_state(AltosState state, int serial) {  		synchronized(backend) { -			backend.putJson(String.format(statePreferenceFormat, state.serial), new AltosJson(state)); -			backend.putInt(statePreferenceLatest, state.serial); +			backend.putJson(String.format(statePreferenceFormat, serial), new AltosJson(state)); +			backend.putInt(statePreferenceLatest, serial);  			flush_preferences();  		}  	} diff --git a/altoslib/AltosPreferencesBackend.java b/altoslib/AltosPreferencesBackend.java index 327b534c..00fd2c6d 100644 --- a/altoslib/AltosPreferencesBackend.java +++ b/altoslib/AltosPreferencesBackend.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; diff --git a/altoslib/AltosPresTemp.java b/altoslib/AltosPresTemp.java new file mode 100644 index 00000000..4cd382c8 --- /dev/null +++ b/altoslib/AltosPresTemp.java @@ -0,0 +1,25 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosPresTemp { +	double	pres = AltosLib.MISSING; +	double	temp = AltosLib.MISSING; + +	public AltosPresTemp(double pres, double temp) { +		this.pres = pres; +		this.temp = temp; +	} +} diff --git a/altoslib/AltosPressure.java b/altoslib/AltosPressure.java new file mode 100644 index 00000000..507a4cee --- /dev/null +++ b/altoslib/AltosPressure.java @@ -0,0 +1,50 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosPressure extends AltosUnits { + +	public double value(double v, boolean imperial_units) { +		if (imperial_units) +			return AltosConvert.pa_to_psi(v); +		return v; +	} + +	public double inverse(double v, boolean imperial_units) { +		if (imperial_units) +			return AltosConvert.psi_to_pa(v); +		return v; +	} + +	public String show_units(boolean imperial_units) { +		if (imperial_units) +			return "psi"; +		return "Pa"; +	} + +	public String say_units(boolean imperial_units) { +		if (imperial_units) +			return "p s i"; +		return "pascals"; +	} + +	public int show_fraction(int width, boolean imperial_units) { +		return width / 9; +	} +} diff --git a/altoslib/AltosProgrammer.java b/altoslib/AltosProgrammer.java index ba04107b..0a828a32 100644 --- a/altoslib/AltosProgrammer.java +++ b/altoslib/AltosProgrammer.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java index 33d7486c..0ea3bfc1 100644 --- a/altoslib/AltosPyro.java +++ b/altoslib/AltosPyro.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.*;  import java.text.*; @@ -290,6 +290,10 @@ public class AltosPyro {  		}  	} +	public AltosPyro() { +		this(0); +	} +  	public String toString() {  		String	ret = String.format("%d", channel); diff --git a/altoslib/AltosPyroName.java b/altoslib/AltosPyroName.java new file mode 100644 index 00000000..0152e479 --- /dev/null +++ b/altoslib/AltosPyroName.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosPyroName extends AltosUnits { + +	public double value(double v, boolean imperial_units) { return v; } + +	public double inverse(double v, boolean imperial_units) { return v; } + +	public String string_value(double v, boolean imperial_units) { +		return AltosLib.igniter_name((int) v); +	} + +	public String show_units(boolean imperial_units) { return "state"; } + +	public String say_units(boolean imperial_units) { return "state"; } + +	public int show_fraction(int width, boolean imperial_units) { return 0; } +} diff --git a/altoslib/AltosQuaternion.java b/altoslib/AltosQuaternion.java index 40786e32..6d6bc12c 100644 --- a/altoslib/AltosQuaternion.java +++ b/altoslib/AltosQuaternion.java @@ -16,12 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosQuaternion {  	double	r;		/* real bit */  	double	x, y, z;	/* imaginary bits */ +	/* Multiply by b */  	public AltosQuaternion multiply(AltosQuaternion b) {  		return new AltosQuaternion(  			this.r * b.r - this.x * b.x - this.y * b.y - this.z * b.z, @@ -31,35 +32,36 @@ public class AltosQuaternion {  	}  	public AltosQuaternion conjugate() { -		return new AltosQuaternion( -			this.r, -			-this.x, -			-this.y, -			-this.z); +		return new AltosQuaternion(this.r, +					   -this.x, +					   -this.y, +					   -this.z);  	}  	public double normal() { -		return (this.r * this.r + -			this.x * this.x + -			this.y * this.y + -			this.z * this.z); +		return Math.sqrt(this.r * this.r + +				 this.x * this.x + +				 this.y * this.y + +				 this.z * this.z);  	} +	/* Scale by a real value */  	public AltosQuaternion scale(double b) { -		return new AltosQuaternion( -			this.r * b, -			this.x * b, -			this.y * b, -			this.z * b); +		return new AltosQuaternion(this.r * b, +					   this.x * b, +					   this.y * b, +					   this.z * b);  	} +	/* Divide by the length to end up with a quaternion of length 1 */  	public AltosQuaternion normalize() {  		double	n = normal();  		if (n <= 0)  			return this; -		return scale(1/Math.sqrt(n)); +		return scale(1/n);  	} +	/* dot product */  	public double dot(AltosQuaternion b) {  		return (this.r * b.r +  			this.x * b.x + @@ -67,10 +69,14 @@ public class AltosQuaternion {  			this.z * b.z);  	} +	/* Rotate 'this' by 'b' */  	public AltosQuaternion rotate(AltosQuaternion b) {  		return (b.multiply(this)).multiply(b.conjugate());  	} +	/* Given two vectors (this and b), compute a quaternion +	 * representing the rotation between them +	 */  	public AltosQuaternion vectors_to_rotation(AltosQuaternion b) {  		/*  		 * The cross product will point orthogonally to the two @@ -145,7 +151,13 @@ public class AltosQuaternion {  		return new AltosQuaternion(1, 0, 0, 0);  	} -	static public AltosQuaternion half_euler(double x, double y, double z) { +	static public AltosQuaternion euler(double x, double y, double z) { + +		/* Halve the euler angles */ +		x = x / 2.0; +		y = y / 2.0; +		z = z / 2.0; +  		double	s_x = Math.sin(x), c_x = Math.cos(x);  		double	s_y = Math.sin(y), c_y = Math.cos(y);  		double	s_z = Math.sin(z), c_z = Math.cos(z);; diff --git a/altoslib/AltosRecordSet.java b/altoslib/AltosRecordSet.java new file mode 100644 index 00000000..91cce624 --- /dev/null +++ b/altoslib/AltosRecordSet.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +import java.util.*; + +public interface AltosRecordSet { +	public AltosCalData cal_data(); +	public void capture_series(AltosDataListener listener); +} diff --git a/altoslib/AltosRectangle.java b/altoslib/AltosRectangle.java index 50b3caa6..810388ed 100644 --- a/altoslib/AltosRectangle.java +++ b/altoslib/AltosRectangle.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosRectangle {  	public int	x, y, width, height; diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java index 59ade871..24b425b7 100644 --- a/altoslib/AltosReplayReader.java +++ b/altoslib/AltosReplayReader.java @@ -16,40 +16,139 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; +import java.util.concurrent.*;  /*   * Open an existing telemetry file and replay it in realtime   */ +class AltosReplay extends AltosDataListener implements Runnable { + +	AltosState	state; +	AltosRecordSet	record_set; +	double		last_time = AltosLib.MISSING; +	Semaphore	semaphore = new Semaphore(1);; +	boolean		done = false; + +	public void set_time(double time) { +		if (last_time != AltosLib.MISSING) { +			semaphore.release(); +			double	delay = Math.min(time - last_time,10); +			if (delay > 0) { +				try { +					Thread.sleep((int) (delay * 1000)); +				} catch (InterruptedException ie) { +				} +			} +		} +		last_time = time; +		super.set_time(time); +		state.set_time(time); +	} + +	public void set_state(int state) { +		super.set_state(state); +		this.state.set_state(state); +	} + +	public void set_rssi(int rssi, int status) { state.set_rssi(rssi, status); } +	public void set_received_time(long received_time) { } + +	public void set_acceleration(double accel) { state.set_acceleration(accel); } +	public void set_pressure(double pa) { state.set_pressure(pa); } +	public void set_thrust(double N) { state.set_thrust(N); } + +	public void set_kalman(double height, double speed, double accel) { state.set_kalman(height, speed, accel); } + +	public void set_temperature(double deg_c) { state.set_temperature(deg_c); } +	public void set_battery_voltage(double volts) { state.set_battery_voltage(volts); } + +	public void set_apogee_voltage(double volts) { state.set_apogee_voltage(volts); } +	public void set_main_voltage(double volts) { state.set_main_voltage(volts); } + +	public void set_gps(AltosGPS gps) { state.set_gps(gps); } + +	public void set_orient(double orient) { state.set_orient(orient); } +	public void set_gyro(double roll, double pitch, double yaw) { state.set_gyro(roll, pitch, yaw); } +	public void set_accel_ground(double along, double across, double through) { state.set_accel_ground(along, across, through); } +	public void set_accel(double along, double across, double through) { state.set_accel(along, across, through); } +	public void set_mag(double along, double across, double through) { state.set_mag(along, across, through); } +	public void set_pyro_voltage(double volts) { state.set_pyro_voltage(volts); } +	public void set_igniter_voltage(double[] voltage) { state.set_igniter_voltage(voltage); } +	public void set_pyro_fired(int pyro_mask) { state.set_pyro_fired(pyro_mask); } +	public void set_companion(AltosCompanion companion) { state.set_companion(companion); } + +	public void run () { +		/* Run the flight */ +		record_set.capture_series(this); +		/* All done, signal that it's over */ +		done = true; +		semaphore.release(); +	} + +	public AltosReplay(AltosRecordSet record_set) { +		super(record_set.cal_data()); +		state = new AltosState(record_set.cal_data()); +		this.record_set = record_set; +		try { +			semaphore.acquire(); +		} catch (InterruptedException ie) { +		} +	} +} +  public class AltosReplayReader extends AltosFlightReader { -	Iterator<AltosState>	iterator; -	File	file; +	File		file; +	AltosReplay	replay; +	Thread		t; +	int		reads; -	public AltosState read() { -		if (iterator.hasNext()) -			return iterator.next(); -		return null; +	public AltosCalData cal_data() { +		return replay.state.cal_data();  	} -	public void close (boolean interrupted) { +	public AltosState read() { +		switch (reads) { +		case 0: +			/* Tell the display that we're in pad mode */ +			replay.state.set_state(AltosLib.ao_flight_pad); +			break; +		case 1: +			t = new Thread(replay); +			t.start(); +			/* fall through */ +		default: +			/* Wait for something to change */ +			try { +				replay.semaphore.acquire(); +			} catch (InterruptedException ie) { +			} +			break; +		} +		reads++; + +		/* When done, let the display know */ +		if (replay.done) +			return null; + +		/* Fake out the received time */ +		replay.state.set_received_time(System.currentTimeMillis()); +		return replay.state;  	} -	public void update(AltosState state) throws InterruptedException { -		/* Make it run in realtime after the rocket leaves the pad */ -		if (state.state() > AltosLib.ao_flight_pad && state.time_change > 0) -			Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); -		state.set_received_time(System.currentTimeMillis()); +	public void close (boolean interrupted) {  	}  	public File backing_file() { return file; } -	public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) { -		iterator = in_iterator; +	public AltosReplayReader(AltosRecordSet record_set, File in_file) { +		reads = 0;  		file = in_file;  		name = file.getName(); +		replay = new AltosReplay(record_set);  	}  } diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java index dcfbda32..46ee2b6e 100644 --- a/altoslib/AltosRomconfig.java +++ b/altoslib/AltosRomconfig.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosRotation.java b/altoslib/AltosRotation.java index 1235d86b..eec8c529 100644 --- a/altoslib/AltosRotation.java +++ b/altoslib/AltosRotation.java @@ -16,11 +16,33 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosRotation extends AltosQuaternion {  	private AltosQuaternion		rotation; +	/* Compute pitch angle from vertical by taking the pad +	 * orientation vector and rotating it by the current total +	 * rotation value. That will be a unit vector pointing along +	 * the airframe axis. The Z value will be the cosine of the +	 * angle from vertical. +	 * +	 * rot = ao_rotation * vertical * ao_rotation° +	 * rot = ao_rotation * (0,0,0,1) * ao_rotation° +	 *     = ((a.z, a.y, -a.x, a.r) * (a.r, -a.x, -a.y, -a.z)) .z +	 * +	 *     = (-a.z * -a.z) + (a.y * -a.y) - (-a.x * -a.x) + (a.r * a.r) +	 *     = a.z² - a.y² - a.x² + a.r² +	 * +	 * rot = ao_rotation * (0, 0, 0, -1) * ao_rotation° +	 *     = ((-a.z, -a.y, a.x, -a.r) * (a.r, -a.x, -a.y, -a.z)) .z +	 * +	 *     = (a.z * -a.z) + (-a.y * -a.y) - (a.x * -a.x) + (-a.r * a.r) +	 *     = -a.z² + a.y² + a.x² - a.r² +	 * +	 * tilt = acos(rot)  (in radians) +	 */ +  	public double tilt() {  		double	rotz = rotation.z * rotation.z - rotation.y * rotation.y - rotation.x * rotation.x + rotation.r * rotation.r; @@ -28,8 +50,11 @@ public class AltosRotation extends AltosQuaternion {  		return tilt;  	} -	public void rotate(double dt, double x, double y, double z) { -		AltosQuaternion	rot = AltosQuaternion.half_euler(x * dt / 2.0, y * dt / 2.0, z * dt / 2.0); +	/* Given euler rotations in three axes, perform a combined rotation using +	 * quaternions +	 */ +	public void rotate(double x, double y, double z) { +		AltosQuaternion	rot = AltosQuaternion.euler(x, y, z);  		rotation = rot.multiply(rotation).normalize();  	} diff --git a/altoslib/AltosRotationRate.java b/altoslib/AltosRotationRate.java new file mode 100644 index 00000000..492f1217 --- /dev/null +++ b/altoslib/AltosRotationRate.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosRotationRate extends AltosUnits { + +	public double value(double p, boolean imperial_units) { +		return p; +	} + +	public double inverse(double p, boolean imperial_units) { +		return p; +	} + +	public String show_units(boolean imperial_units) { +		return "°/sec"; +	} + +	public String say_units(boolean imperial_units) { +		return "degrees per second"; +	} + +	public int show_fraction(int width, boolean imperial_units) { +		return 1; +	} +} diff --git a/altoslib/AltosSavedState.java b/altoslib/AltosSavedState.java index 76d12faf..66876864 100644 --- a/altoslib/AltosSavedState.java +++ b/altoslib/AltosSavedState.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosSelfFlash.java b/altoslib/AltosSelfFlash.java index ae7cd69a..53782172 100644 --- a/altoslib/AltosSelfFlash.java +++ b/altoslib/AltosSelfFlash.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*; diff --git a/altoslib/AltosSensorEMini.java b/altoslib/AltosSensorEMini.java index 2581685f..1bdbb60c 100644 --- a/altoslib/AltosSensorEMini.java +++ b/altoslib/AltosSensorEMini.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.TimeoutException; @@ -26,15 +26,25 @@ public class AltosSensorEMini {  	public int	main;  	public int	batt; -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link, int version) throws InterruptedException {  		try {  			AltosSensorEMini	sensor_emini = new AltosSensorEMini(link); +			AltosCalData		cal_data = listener.cal_data();  			if (sensor_emini == null)  				return; -			state.set_battery_voltage(AltosConvert.easy_mini_voltage(sensor_emini.batt, config_data.serial)); -			state.set_apogee_voltage(AltosConvert.easy_mini_voltage(sensor_emini.apogee, config_data.serial)); -			state.set_main_voltage(AltosConvert.easy_mini_voltage(sensor_emini.main, config_data.serial)); +			switch (version) { +			case 1: +				listener.set_battery_voltage(AltosConvert.easy_mini_1_voltage(sensor_emini.batt, cal_data.serial)); +				listener.set_apogee_voltage(AltosConvert.easy_mini_1_voltage(sensor_emini.apogee, cal_data.serial)); +				listener.set_main_voltage(AltosConvert.easy_mini_1_voltage(sensor_emini.main, cal_data.serial)); +				break; +			case 2: +				listener.set_battery_voltage(AltosConvert.easy_mini_2_voltage(sensor_emini.batt)); +				listener.set_apogee_voltage(AltosConvert.easy_mini_2_voltage(sensor_emini.apogee)); +				listener.set_main_voltage(AltosConvert.easy_mini_2_voltage(sensor_emini.main)); +				break; +			}  		} catch (TimeoutException te) {  		} diff --git a/altoslib/AltosSensorMM.java b/altoslib/AltosSensorMM.java index d79c0805..00873afe 100644 --- a/altoslib/AltosSensorMM.java +++ b/altoslib/AltosSensorMM.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorMega.java b/altoslib/AltosSensorMega.java index 63c7a0ce..e58b03a1 100644 --- a/altoslib/AltosSensorMega.java +++ b/altoslib/AltosSensorMega.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.TimeoutException; @@ -89,18 +89,18 @@ class AltosSensorMega {  		}  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try {  			AltosSensorMega	sensor_mega = new AltosSensorMega(link); -			state.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_mega.v_batt)); -			state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[4])); -			state.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[5])); +			listener.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_mega.v_batt)); +			listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[4])); +			listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[5])); -			double[]	ignitor_voltage = new double[4]; +			double[]	igniter_voltage = new double[4];  			for (int i = 0; i < 4; i++) -				ignitor_voltage[i] = AltosConvert.mega_pyro_voltage(sensor_mega.sense[i]); -			state.set_ignitor_voltage(ignitor_voltage); +				igniter_voltage[i] = AltosConvert.mega_pyro_voltage(sensor_mega.sense[i]); +			listener.set_igniter_voltage(igniter_voltage);  		} catch (TimeoutException te) {  		} diff --git a/altoslib/AltosSensorMetrum.java b/altoslib/AltosSensorMetrum.java index cb163911..e01d57cc 100644 --- a/altoslib/AltosSensorMetrum.java +++ b/altoslib/AltosSensorMetrum.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.TimeoutException; @@ -53,12 +53,12 @@ class AltosSensorMetrum {  		}  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try {  			AltosSensorMetrum	sensor_metrum = new AltosSensorMetrum(link); -			state.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_metrum.v_batt)); -			state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_a)); -			state.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_m)); +			listener.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_metrum.v_batt)); +			listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_a)); +			listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_m));  		} catch (TimeoutException te) {  		}  	} diff --git a/altoslib/AltosSensorTGPS.java b/altoslib/AltosSensorTGPS.java index 9c2bcb10..14514413 100644 --- a/altoslib/AltosSensorTGPS.java +++ b/altoslib/AltosSensorTGPS.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.TimeoutException; @@ -24,13 +24,13 @@ public class AltosSensorTGPS {  	public int	tick;  	public int	batt; -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try {  			AltosSensorTGPS	sensor_tgps = new AltosSensorTGPS(link);  			if (sensor_tgps == null)  				return; -			state.set_battery_voltage(AltosConvert.tele_gps_voltage(sensor_tgps.batt)); +			listener.set_battery_voltage(AltosConvert.tele_gps_voltage(sensor_tgps.batt));  		} catch (TimeoutException te) {  		} diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java index 5d1b1b7f..bdedaa9c 100644 --- a/altoslib/AltosSensorTM.java +++ b/altoslib/AltosSensorTM.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.TimeoutException; @@ -29,18 +29,19 @@ public class AltosSensorTM {  	public int	drogue;  	public int	main; -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try {  			AltosSensorTM	sensor_tm = new AltosSensorTM(link); +			AltosCalData	cal_data = listener.cal_data();  			if (sensor_tm == null)  				return; -			state.set_accel(sensor_tm.accel); -			state.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres)); -			state.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp)); -			state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt)); -			state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.drogue)); -			state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.main)); +			listener.set_acceleration(cal_data.acceleration((sensor_tm.accel))); +			listener.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres)); +			listener.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp)); +			listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt)); +			listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(sensor_tm.drogue)); +			listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(sensor_tm.main));  		} catch (TimeoutException te) {  		} diff --git a/altoslib/AltosSensorTMini2.java b/altoslib/AltosSensorTMini2.java index 7e00abd0..9b5a1854 100644 --- a/altoslib/AltosSensorTMini2.java +++ b/altoslib/AltosSensorTMini2.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.TimeoutException; @@ -26,15 +26,15 @@ public class AltosSensorTMini2 {  	public int	main;  	public int	batt; -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try {  			AltosSensorTMini2	sensor_tmini = new AltosSensorTMini2(link);  			if (sensor_tmini == null)  				return; -			state.set_battery_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.batt)); -			state.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.apogee)); -			state.set_main_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.main)); +			listener.set_battery_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.batt)); +			listener.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.apogee)); +			listener.set_main_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.main));  		} catch (TimeoutException te) {  		} diff --git a/altoslib/AltosSensorTMini3.java b/altoslib/AltosSensorTMini3.java index 19d514d7..b92def03 100644 --- a/altoslib/AltosSensorTMini3.java +++ b/altoslib/AltosSensorTMini3.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.util.concurrent.TimeoutException; @@ -26,15 +26,15 @@ public class AltosSensorTMini3 {  	public int	main;  	public int	batt; -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {  		try {  			AltosSensorTMini3	sensor_tmini = new AltosSensorTMini3(link);  			if (sensor_tmini == null)  				return; -			state.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(sensor_tmini.batt)); -			state.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.apogee)); -			state.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.main)); +			listener.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(sensor_tmini.batt)); +			listener.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.apogee)); +			listener.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.main));  		} catch (TimeoutException te) {  		} diff --git a/altoslib/AltosSpeed.java b/altoslib/AltosSpeed.java index 465c190c..2a8ccedc 100644 --- a/altoslib/AltosSpeed.java +++ b/altoslib/AltosSpeed.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosSpeed extends AltosUnits { diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index fd2684db..9ee3d57d 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -20,11 +20,9 @@   * Track flight state from telemetry or eeprom data stream   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; -import java.io.*; - -public class AltosState implements Cloneable { +public class AltosState extends AltosDataListener {  	public static final int set_position = 1;  	public static final int set_gps = 2; @@ -40,12 +38,8 @@ public class AltosState implements Cloneable {  	public long	received_time; -	public double	time; -	public double	prev_time; -	public double	time_change; -	public int	tick; -	private int	prev_tick; -	public int	boost_tick; +	public int	rssi; +	public int	status;  	class AltosValue {  		double	value; @@ -290,22 +284,9 @@ public class AltosState implements Cloneable {  		}  	} -	private int	state; -	public int	flight; -	public int	serial; -	public int	altitude_32; -	public int	receiver_serial;  	public boolean	landed;  	public boolean	ascent;	/* going up? */  	public boolean	boost;	/* under power */ -	public int	rssi; -	public int	status; -	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;  	private double pressure_to_altitude(double p) {  		if (p == AltosLib.MISSING) @@ -448,6 +429,11 @@ public class AltosState implements Cloneable {  	}  	public void set_altitude(double new_altitude) { +		double old_altitude = altitude.value(); +		if (old_altitude != AltosLib.MISSING) { +			while (old_altitude - new_altitude > 32000) +				new_altitude += 65536.0; +		}  		altitude.set_measured(new_altitude, time);  	} @@ -515,6 +501,9 @@ public class AltosState implements Cloneable {  		pressure.set(p, time);  	} +	public void set_thrust(double N) { +	} +  	public double baro_height() {  		double a = altitude();  		double g = ground_altitude(); @@ -667,6 +656,11 @@ public class AltosState implements Cloneable {  	public AltosValue	kalman_height, kalman_speed, kalman_acceleration;  	public void set_kalman(double height, double speed, double acceleration) { +		double old_height = kalman_height.value(); +		if (old_height != AltosLib.MISSING) { +			while (old_height - height > 32000) +				height += 65536; +		}  		kalman_height.set(height, time);  		kalman_speed.set(speed, time);  		kalman_acceleration.set(acceleration, time); @@ -678,16 +672,10 @@ public class AltosState implements Cloneable {  	public double	apogee_voltage;  	public double	main_voltage; -	public double	ignitor_voltage[]; +	public double	igniter_voltage[];  	public AltosGPS	gps; -	public AltosGPS	temp_gps; -	public int temp_gps_sat_tick;  	public boolean	gps_pending; -	public int gps_sequence; - -	public AltosIMU	imu; -	public AltosMag	mag;  	public static final int MIN_PAD_SAMPLES = 10; @@ -699,6 +687,7 @@ public class AltosState implements Cloneable {  	public AltosGreatCircle from_pad;  	public double	elevation;	/* from pad */ +	public double	distance;	/* distance along ground */  	public double	range;		/* total distance */  	public double	gps_height; @@ -708,20 +697,7 @@ public class AltosState implements Cloneable {  	public int	speak_tick;  	public double	speak_altitude; -	public String	callsign; -	public String	firmware_version; - -	public double	accel_plus_g; -	public double	accel_minus_g; -	public double	accel;  	public double	ground_accel; -	public double	ground_accel_avg; - -	public int	log_format; -	public int	log_space; -	public String	product; - -	public AltosMs5607	baro;  	public AltosCompanion	companion; @@ -740,23 +716,11 @@ public class AltosState implements Cloneable {  		received_time = System.currentTimeMillis();  		time = AltosLib.MISSING; -		time_change = AltosLib.MISSING; -		prev_time = AltosLib.MISSING; -		tick = AltosLib.MISSING; -		prev_tick = AltosLib.MISSING; -		boost_tick = AltosLib.MISSING;  		state = AltosLib.ao_flight_invalid; -		flight = AltosLib.MISSING;  		landed = false;  		boost = false;  		rssi = AltosLib.MISSING;  		status = 0; -		device_type = AltosLib.MISSING; -		config_major = AltosLib.MISSING; -		config_minor = AltosLib.MISSING; -		apogee_delay = AltosLib.MISSING; -		main_deploy = AltosLib.MISSING; -		flight_log_max = AltosLib.MISSING;  		ground_altitude = new AltosCValue();  		ground_pressure = new AltosGroundPressure(); @@ -771,43 +735,40 @@ public class AltosState implements Cloneable {  		pyro_voltage = AltosLib.MISSING;  		apogee_voltage = AltosLib.MISSING;  		main_voltage = AltosLib.MISSING; -		ignitor_voltage = null; +		igniter_voltage = null;  		kalman_height = new AltosValue();  		kalman_speed = new AltosValue();  		kalman_acceleration = new AltosValue();  		gps = null; -		temp_gps = null; -		temp_gps_sat_tick = 0; -		gps_sequence = 0;  		gps_pending = false; -		imu = null;  		last_imu_time = AltosLib.MISSING;  		rotation = null; -		ground_rotation = null; - -		mag = null; -		accel_zero_along = AltosLib.MISSING; -		accel_zero_across = AltosLib.MISSING; -		accel_zero_through = AltosLib.MISSING;  		accel_ground_along = AltosLib.MISSING;  		accel_ground_across = AltosLib.MISSING;  		accel_ground_through = AltosLib.MISSING; -		pad_orientation = AltosLib.MISSING; +		accel_along = AltosLib.MISSING; +		accel_across = AltosLib.MISSING; +		accel_through = AltosLib.MISSING; -		gyro_zero_roll = AltosLib.MISSING; -		gyro_zero_pitch = AltosLib.MISSING; -		gyro_zero_yaw = AltosLib.MISSING; +		gyro_roll = AltosLib.MISSING; +		gyro_pitch = AltosLib.MISSING; +		gyro_yaw = AltosLib.MISSING; + +		mag_along = AltosLib.MISSING; +		mag_across = AltosLib.MISSING; +		mag_through = AltosLib.MISSING;  		set_npad(0);  		ngps = 0;  		from_pad = null;  		elevation = AltosLib.MISSING; +		distance = AltosLib.MISSING;  		range = AltosLib.MISSING;  		gps_height = AltosLib.MISSING; @@ -825,32 +786,14 @@ public class AltosState implements Cloneable {  		speak_tick = AltosLib.MISSING;  		speak_altitude = AltosLib.MISSING; -		callsign = null; -		firmware_version = null; - -		accel_plus_g = AltosLib.MISSING; -		accel_minus_g = AltosLib.MISSING; -		accel = AltosLib.MISSING; -  		ground_accel = AltosLib.MISSING; -		ground_accel_avg = AltosLib.MISSING; - -		log_format = AltosLib.MISSING; -		log_space = AltosLib.MISSING; -		product = null; -		serial = AltosLib.MISSING; -		receiver_serial = AltosLib.MISSING; -		altitude_32 = AltosLib.MISSING; -		baro = null;  		companion = null;  		pyro_fired = 0;  	}  	void finish_update() { -		prev_tick = tick; -  		ground_altitude.finish_update();  		altitude.finish_update();  		pressure.finish_update(); @@ -863,156 +806,12 @@ public class AltosState implements Cloneable {  		kalman_acceleration.finish_update();  	} -	void copy(AltosState old) { - -		if (old == null) { -			init(); -			return; -		} - -		received_time = old.received_time; -		time = old.time; -		time_change = old.time_change; -		prev_time = old.time; - -		tick = old.tick; -		prev_tick = old.tick; -		boost_tick = old.boost_tick; - -		state = old.state; -		flight = old.flight; -		landed = old.landed; -		ascent = old.ascent; -		boost = old.boost; -		rssi = old.rssi; -		status = old.status; -		device_type = old.device_type; -		config_major = old.config_major; -		config_minor = old.config_minor; -		apogee_delay = old.apogee_delay; -		main_deploy = old.main_deploy; -		flight_log_max = old.flight_log_max; - -		set = 0; - -		ground_pressure.copy(old.ground_pressure); -		ground_altitude.copy(old.ground_altitude); -		altitude.copy(old.altitude); -		pressure.copy(old.pressure); -		speed.copy(old.speed); -		acceleration.copy(old.acceleration); -		orient.copy(old.orient); - -		battery_voltage = old.battery_voltage; -		pyro_voltage = old.pyro_voltage; -		temperature = old.temperature; -		apogee_voltage = old.apogee_voltage; -		main_voltage = old.main_voltage; -		ignitor_voltage = old.ignitor_voltage; - -		kalman_height.copy(old.kalman_height); -		kalman_speed.copy(old.kalman_speed); -		kalman_acceleration.copy(old.kalman_acceleration); - -		if (old.gps != null) -			gps = old.gps.clone(); -		else -			gps = null; -		if (old.temp_gps != null) -			temp_gps = old.temp_gps.clone(); -		else -			temp_gps = null; -		temp_gps_sat_tick = old.temp_gps_sat_tick; -		gps_sequence = old.gps_sequence; -		gps_pending = old.gps_pending; - -		if (old.imu != null) -			imu = old.imu.clone(); -		else -			imu = null; -		last_imu_time = old.last_imu_time; - -		if (old.rotation != null) -			rotation = new AltosRotation (old.rotation); - -		if (old.ground_rotation != null) { -			ground_rotation = new AltosRotation(old.ground_rotation); -		} - -		accel_zero_along = old.accel_zero_along; -		accel_zero_across = old.accel_zero_across; -		accel_zero_through = old.accel_zero_through; - -		accel_ground_along = old.accel_ground_along; -		accel_ground_across = old.accel_ground_across; -		accel_ground_through = old.accel_ground_through; -		pad_orientation = old.pad_orientation; - -		gyro_zero_roll = old.gyro_zero_roll; -		gyro_zero_pitch = old.gyro_zero_pitch; -		gyro_zero_yaw = old.gyro_zero_yaw; - -		if (old.mag != null) -			mag = old.mag.clone(); -		else -			mag = null; - -		npad = old.npad; -		gps_waiting = old.gps_waiting; -		gps_ready = old.gps_ready; -		ngps = old.ngps; - -		if (old.from_pad != null) -			from_pad = old.from_pad.clone(); -		else -			from_pad = null; - -		elevation = old.elevation; -		range = old.range; - -		gps_height = old.gps_height; - -		gps_altitude.copy(old.gps_altitude); -		gps_ground_altitude.copy(old.gps_ground_altitude); -		gps_ground_speed.copy(old.gps_ground_speed); -		gps_ascent_rate.copy(old.gps_ascent_rate); -		gps_course.copy(old.gps_course); -		gps_speed.copy(old.gps_speed); - -		pad_lat = old.pad_lat; -		pad_lon = old.pad_lon; -		pad_alt = old.pad_alt; - -		speak_tick = old.speak_tick; -		speak_altitude = old.speak_altitude; - -		callsign = old.callsign; -		firmware_version = old.firmware_version; - -		accel_plus_g = old.accel_plus_g; -		accel_minus_g = old.accel_minus_g; -		accel = old.accel; -		ground_accel = old.ground_accel; -		ground_accel_avg = old.ground_accel_avg; - -		log_format = old.log_format; -		log_space = old.log_space; -		product = old.product; -		serial = old.serial; -		receiver_serial = old.receiver_serial; -		altitude_32 = old.altitude_32; - -		baro = old.baro; -		companion = old.companion; - -		pyro_fired = old.pyro_fired; -	} -  	void update_time() {  	}  	void update_gps() {  		elevation = AltosLib.MISSING; +		distance = AltosLib.MISSING;  		range = AltosLib.MISSING;  		if (gps == null) @@ -1054,36 +853,15 @@ public class AltosState implements Cloneable {  				h = 0;  			from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h);  			elevation = from_pad.elevation; +			distance = from_pad.distance;  			range = from_pad.range;  		}  	} -	public void set_tick(int new_tick) { -		if (new_tick != AltosLib.MISSING) { -			if (prev_tick != AltosLib.MISSING) { -				while (new_tick < prev_tick - 1000) { -					new_tick += 65536; -				} -			} -			tick = new_tick; -			time = tick / 100.0; -			time_change = time - prev_time; -		} -	} - -	public void set_boost_tick(int boost_tick) { -		if (boost_tick != AltosLib.MISSING) -			this.boost_tick = boost_tick; -	} -  	public String state_name() {  		return AltosLib.state_name(state);  	} -	public void set_product(String product) { -		this.product = product; -	} -  	public void set_state(int state) {  		if (state != AltosLib.ao_flight_invalid) {  			this.state = state; @@ -1097,96 +875,8 @@ public class AltosState implements Cloneable {  		return state;  	} -	public void set_device_type(int device_type) { -		this.device_type = device_type; -		switch (device_type) { -		case AltosLib.product_telegps: -			this.state = AltosLib.ao_flight_stateless; -			break; -		} -	} - -	public void set_log_format(int log_format) { -		this.log_format = log_format; -		switch (log_format) { -		case AltosLib.AO_LOG_FORMAT_TELEGPS: -			this.state = AltosLib.ao_flight_stateless; -			break; -		} -	} - -	public void set_log_space(int log_space) { -		this.log_space = log_space; -	} - -	public void set_flight_params(int apogee_delay, int main_deploy) { -		this.apogee_delay = apogee_delay; -		this.main_deploy = main_deploy; -	} - -	public void set_config(int major, int minor, int flight_log_max) { -		config_major = major; -		config_minor = minor; -		this.flight_log_max = flight_log_max; -	} - -	public void set_callsign(String callsign) { -		this.callsign = callsign; -	} - -	public void set_firmware_version(String version) { -		firmware_version = version; -	} - -	public int compare_version(String other_version) { -		if (firmware_version == null) -			return AltosLib.MISSING; -		return AltosLib.compare_version(firmware_version, other_version); -	} -  	private void re_init() { -		int bt = boost_tick; -		int rs = receiver_serial;  		init(); -		boost_tick = bt; -		receiver_serial = rs; -	} - -	public void set_flight(int flight) { - -		/* When the flight changes, reset the state */ -		if (flight != AltosLib.MISSING) { -			if (this.flight != AltosLib.MISSING && -			    this.flight != flight) { -				re_init(); -			} -			this.flight = flight; -		} -	} - -	public void set_serial(int serial) { -		/* When the serial changes, reset the state */ -		if (serial != AltosLib.MISSING) { -			if (this.serial != AltosLib.MISSING && -			    this.serial != serial) { -				re_init(); -			} -			this.serial = serial; -		} -	} - -	public void set_receiver_serial(int serial) { -		if (serial != AltosLib.MISSING) -			receiver_serial = serial; -	} - -	public boolean altitude_32() { -		return altitude_32 == 1; -	} - -	public void set_altitude_32(int altitude_32) { -		if (altitude_32 != AltosLib.MISSING) -			this.altitude_32 = altitude_32;  	}  	public int rssi() { @@ -1206,42 +896,24 @@ public class AltosState implements Cloneable {  		received_time = ms;  	} -	public void set_gps(AltosGPS gps, int sequence) { +	public void set_gps(AltosGPS gps) {  		if (gps != null) { -			this.gps = gps.clone(); -			gps_sequence = sequence; +			this.gps = gps;  			update_gps();  			set |= set_gps;  		}  	} - -	public double	accel_zero_along; -	public double	accel_zero_across; -	public double	accel_zero_through; -  	public AltosRotation	rotation; -	public AltosRotation	ground_rotation; - -	public void set_accel_zero(double zero_along, double zero_across, double zero_through) { -		if (zero_along != AltosLib.MISSING) { -			accel_zero_along = zero_along; -			accel_zero_across = zero_across; -			accel_zero_through = zero_through; -		} -	} - -	public int pad_orientation;  	public double	accel_ground_along, accel_ground_across, accel_ground_through;  	void update_pad_rotation() { -		if (pad_orientation != AltosLib.MISSING && accel_ground_along != AltosLib.MISSING) { -			rotation = new AltosRotation(AltosIMU.convert_accel(accel_ground_across - accel_zero_across), -						     AltosIMU.convert_accel(accel_ground_through - accel_zero_through), -						     AltosIMU.convert_accel(accel_ground_along - accel_zero_along), -						     pad_orientation); -			ground_rotation = rotation; +		if (cal_data().pad_orientation != AltosLib.MISSING && accel_ground_along != AltosLib.MISSING) { +			rotation = new AltosRotation(AltosIMU.convert_accel(accel_ground_across - cal_data().accel_zero_across), +						     AltosIMU.convert_accel(accel_ground_through - cal_data().accel_zero_through), +						     AltosIMU.convert_accel(accel_ground_along - cal_data().accel_zero_along), +						     cal_data().pad_orientation);  			orient.set_computed(rotation.tilt(), time);  		}  	} @@ -1253,197 +925,95 @@ public class AltosState implements Cloneable {  		update_pad_rotation();  	} -	public void set_pad_orientation(int pad_orientation) { -		this.pad_orientation = pad_orientation; -		update_pad_rotation(); -	} - -	public double	gyro_zero_roll; -	public double	gyro_zero_pitch; -	public double	gyro_zero_yaw; - -	public void set_gyro_zero(double roll, double pitch, double yaw) { -		if (roll != AltosLib.MISSING) { -			gyro_zero_roll = roll; -			gyro_zero_pitch = pitch; -			gyro_zero_yaw = yaw; -		} -	} -  	public double	last_imu_time; -	private double radians(double degrees) { -		if (degrees == AltosLib.MISSING) -			return AltosLib.MISSING; -		return degrees * Math.PI / 180.0; -	} -  	private void update_orient() {  		if (last_imu_time != AltosLib.MISSING) {  			double	t = time - last_imu_time; -			double	pitch = radians(gyro_pitch()); -			double	yaw = radians(gyro_yaw()); -			double	roll = radians(gyro_roll()); +			if (t > 0 && gyro_pitch != AltosLib.MISSING && rotation != null) { +				double	pitch = AltosConvert.degrees_to_radians(gyro_pitch) * t; +				double	yaw = AltosConvert.degrees_to_radians(gyro_yaw) * t; +				double	roll = AltosConvert.degrees_to_radians(gyro_roll) * t; -			if (t > 0 & pitch != AltosLib.MISSING && rotation != null) { -				rotation.rotate(t, pitch, yaw, roll); +				rotation.rotate(pitch, yaw, roll);  				orient.set_computed(rotation.tilt(), time);  			}  		}  		last_imu_time = time;  	} -	public void set_imu(AltosIMU imu) { -		if (imu != null) -			imu = imu.clone(); -		this.imu = imu; +	private double	gyro_roll, gyro_pitch, gyro_yaw; + +	public void set_gyro(double roll, double pitch, double yaw) { +		gyro_roll = roll; +		gyro_pitch = pitch; +		gyro_yaw = yaw;  		update_orient();  	} -	private double gyro_zero_overflow(double first) { -		double v = first / 128.0; -		if (v < 0) -			v = Math.ceil(v); -		else -			v = Math.floor(v); -		return v * 128.0; -	} +	private double accel_along, accel_across, accel_through; -	public void check_imu_wrap(AltosIMU imu) { -		if (this.imu == null) { -			gyro_zero_roll += gyro_zero_overflow(imu.gyro_roll); -			gyro_zero_pitch += gyro_zero_overflow(imu.gyro_pitch); -			gyro_zero_yaw += gyro_zero_overflow(imu.gyro_yaw); -		} +	public void set_accel(double along, double across, double through) { +		accel_along = along; +		accel_across = across; +		accel_through = through; +		update_orient();  	}  	public double accel_along() { -		if (imu != null && accel_zero_along != AltosLib.MISSING) -			return AltosIMU.convert_accel(imu.accel_along - accel_zero_along); -		return AltosLib.MISSING; +		return accel_along;  	}  	public double accel_across() { -		if (imu != null && accel_zero_across != AltosLib.MISSING) -			return AltosIMU.convert_accel(imu.accel_across - accel_zero_across); -		return AltosLib.MISSING; +		return accel_across;  	}  	public double accel_through() { -		if (imu != null && accel_zero_through != AltosLib.MISSING) -			return AltosIMU.convert_accel(imu.accel_through - accel_zero_through); -		return AltosLib.MISSING; +		return accel_through;  	}  	public double gyro_roll() { -		if (imu != null && gyro_zero_roll != AltosLib.MISSING) { -			return AltosIMU.convert_gyro(imu.gyro_roll - gyro_zero_roll); -		} -		return AltosLib.MISSING; +		return gyro_roll;  	}  	public double gyro_pitch() { -		if (imu != null && gyro_zero_pitch != AltosLib.MISSING) { -			return AltosIMU.convert_gyro(imu.gyro_pitch - gyro_zero_pitch); -		} -		return AltosLib.MISSING; +		return gyro_pitch;  	}  	public double gyro_yaw() { -		if (imu != null && gyro_zero_yaw != AltosLib.MISSING) { -			return AltosIMU.convert_gyro(imu.gyro_yaw - gyro_zero_yaw); -		} -		return AltosLib.MISSING; +		return gyro_yaw;  	} -	public void set_mag(AltosMag mag) { -		this.mag = mag.clone(); +	private double mag_along, mag_across, mag_through; + +	public void set_mag(double along, double across, double through) { +		mag_along = along; +		mag_across = across; +		mag_through = through;  	}  	public double mag_along() { -		if (mag != null) -			return AltosMag.convert_gauss(mag.along); -		return AltosLib.MISSING; +		return mag_along;  	}  	public double mag_across() { -		if (mag != null) -			return AltosMag.convert_gauss(mag.across); -		return AltosLib.MISSING; +		return mag_across;  	}  	public double mag_through() { -		if (mag != null) -			return AltosMag.convert_gauss(mag.through); -		return AltosLib.MISSING; -	} - -	public AltosMs5607 make_baro() { -		if (baro == null) -			baro = new AltosMs5607(); -		return baro; -	} - -	public void set_ms5607(AltosMs5607 ms5607) { -		baro = ms5607; - -		if (baro != null) { -			set_pressure(baro.pa); -			set_temperature(baro.cc / 100.0); -		} -	} - -	public void set_ms5607(int pres, int temp) { -		if (baro != null) { -			baro.set(pres, temp); - -			set_pressure(baro.pa); -			set_temperature(baro.cc / 100.0); -		} +		return mag_through;  	}  	public void set_companion(AltosCompanion companion) {  		this.companion = companion;  	} -	void update_accel() { -		if (accel == AltosLib.MISSING) -			return; -		if (accel_plus_g == AltosLib.MISSING) -			return; -		if (accel_minus_g == AltosLib.MISSING) -			return; - -		double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0; -		double counts_per_mss = counts_per_g / 9.80665; -		acceleration.set_measured((accel_plus_g - accel) / counts_per_mss, time); -	} - -	public void set_accel_g(double accel_plus_g, double accel_minus_g) { -		if (accel_plus_g != AltosLib.MISSING) { -			this.accel_plus_g = accel_plus_g; -			this.accel_minus_g = accel_minus_g; -			update_accel(); -		} -	} - -	public void set_ground_accel(double ground_accel) { -		if (ground_accel != AltosLib.MISSING) -			this.ground_accel = ground_accel; -	} - -	public void set_accel(double accel) { -		if (accel != AltosLib.MISSING) { -			this.accel = accel; -			if (state == AltosLib.ao_flight_pad) { -				if (ground_accel_avg == AltosLib.MISSING) -					ground_accel_avg = accel; -				else -					ground_accel_avg = (ground_accel_avg * 7 + accel) / 8; -			} +	public void set_acceleration(double acceleration) { +		if (acceleration != AltosLib.MISSING) { +			this.acceleration.set_measured(acceleration, time); +			set |= set_data;  		} -		update_accel();  	}  	public void set_temperature(double temperature) { @@ -1481,78 +1051,21 @@ public class AltosState implements Cloneable {  		}  	} -	public void set_ignitor_voltage(double[] voltage) { -		this.ignitor_voltage = voltage; +	public void set_igniter_voltage(double[] voltage) { +		this.igniter_voltage = voltage;  	}  	public void set_pyro_fired(int fired) {  		this.pyro_fired = fired;  	} -	public double time_since_boost() { -		if (tick == AltosLib.MISSING) -			return 0.0; - -		if (boost_tick == AltosLib.MISSING) -			return tick / 100.0; -		return (tick - boost_tick) / 100.0; -	} - -	public boolean valid() { -		return tick != AltosLib.MISSING && serial != AltosLib.MISSING; -	} - -	public AltosGPS make_temp_gps(boolean sats) { -		if (temp_gps == null) { -			temp_gps = new AltosGPS(gps); -		} -		gps_pending = true; -		if (sats) { -			if (tick != temp_gps_sat_tick) -				temp_gps.cc_gps_sat = null; -			temp_gps_sat_tick = tick; -		} -		return temp_gps; -	} - -	public void set_temp_gps() { -		set_gps(temp_gps, gps_sequence + 1); -		gps_pending = false; -		temp_gps = null; -	} - -	public AltosState clone() { -		AltosState s = new AltosState(); -		s.copy(this); - -		/* Code to test state save/restore. Enable only for that purpose -		 */ -		if (false) { -			AltosJson	json = new AltosJson(this); -			String		onetrip = json.toPrettyString(); -			AltosJson	back = AltosJson.fromString(onetrip); -			AltosState	tripstate = (AltosState) back.make(this.getClass()); -			AltosJson	tripjson = new AltosJson(tripstate); -			String		twotrip = tripjson.toPrettyString(); - -			if (!onetrip.equals(twotrip)) { -				try { -					FileWriter one_file = new FileWriter("one.json", true); -					one_file.write(onetrip); -					one_file.flush(); -					FileWriter two_file = new FileWriter("two.json", true); -					two_file.write(twotrip); -					two_file.flush(); -				} catch (Exception e) { -				} -				System.out.printf("json error\n"); -				System.exit(1); -			} -		} -		return s; +	public AltosState() { +		Thread.dumpStack(); +		init();  	} -	public AltosState () { +	public AltosState (AltosCalData cal_data) { +		super(cal_data);  		init();  	}  } diff --git a/altoslib/AltosStateName.java b/altoslib/AltosStateName.java new file mode 100644 index 00000000..5ba21f27 --- /dev/null +++ b/altoslib/AltosStateName.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosStateName extends AltosUnits { + +	public double value(double v, boolean imperial_units) { return v; } + +	public double inverse(double v, boolean imperial_units) { return v; } + +	public String string_value(double v, boolean imperial_units) { +		return AltosLib.state_name((int) v); +	} + +	public String show_units(boolean imperial_units) { return "state"; } + +	public String say_units(boolean imperial_units) { return "state"; } + +	public int show_fraction(int width, boolean imperial_units) { return 0; } +} diff --git a/altoslib/AltosStringInputStream.java b/altoslib/AltosStringInputStream.java new file mode 100644 index 00000000..48fff3ea --- /dev/null +++ b/altoslib/AltosStringInputStream.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +import java.util.*; +import java.io.*; + +public class AltosStringInputStream extends InputStream { + +	String	s; +	int	at; +	int	mark; + +	public int available() { +		return s.length() - at; +	} + +	public void mark(int read_limit) { +		mark = at; +	} + +	public boolean markSupported() { +		return true; +	} + +	public int read() { +		if (at == s.length()) +			return -1; +		return (int) s.charAt(at++); +	} + +	public void reset() { +		at = mark; +	} + +	public long skip(long n) throws IOException { +		if (n < 0) n = 0; + +		if (at + n > s.length()) +			n = s.length() - at; +		at += n; +		return n; +	} + +	public AltosStringInputStream(String s) { +		this.s = s; +		this.at = 0; +	} +} diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index f830bf35..7d576942 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*; @@ -24,13 +24,16 @@ import java.text.*;   * Telemetry data contents   */ -public abstract class AltosTelemetry implements AltosStateUpdate { +public abstract class AltosTelemetry implements AltosDataProvider { +	int[]	bytes;  	/* All telemetry packets have these fields */ -	public int	tick; -	public int	serial; -	public int	rssi; -	public int	status; +	public int rssi() { return AltosConvert.telem_to_rssi(AltosLib.int8(bytes, bytes.length - 3)); } +	public int status() { return AltosLib.uint8(bytes, bytes.length - 2); } + +	/* All telemetry packets report these fields in some form */ +	public abstract int serial(); +	public abstract int tick();  	/* Mark when we received the packet */  	long		received_time; @@ -43,13 +46,13 @@ public abstract class AltosTelemetry implements AltosStateUpdate {  		return sum == bytes[bytes.length - 1];  	} -	public void update_state(AltosState state) { -		state.set_serial(serial); -		if (state.state() == AltosLib.ao_flight_invalid) -			state.set_state(AltosLib.ao_flight_startup); -		state.set_tick(tick); -		state.set_rssi(rssi, status); -		state.set_received_time(received_time); +	public void provide_data(AltosDataListener listener) { +		listener.set_serial(serial()); +		if (listener.state == AltosLib.ao_flight_invalid) +			listener.set_state(AltosLib.ao_flight_startup); +		listener.set_tick(tick()); +		listener.set_rssi(rssi(), status()); +		listener.set_received_time(received_time);  	}  	final static int PKT_APPEND_STATUS_1_CRC_OK		= (1 << 7); @@ -88,12 +91,6 @@ public abstract class AltosTelemetry implements AltosStateUpdate {  		if (!cksum(bytes))  			throw new ParseException(String.format("invalid line \"%s\"", hex), 0); -		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 AltosLib.ao_telemetry_standard_len + 4: @@ -108,35 +105,18 @@ public abstract class AltosTelemetry implements AltosStateUpdate {  		default:  			throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0);  		} -		if (telem != null) { -			telem.received_time = System.currentTimeMillis(); -			telem.rssi = rssi; -			telem.status = status; -		}  		return telem;  	} -	public static int extend_height(AltosState state, int height_16) { -		double	compare_height; -		int	height = height_16; - -		if (state.gps != null && state.gps.alt != AltosLib.MISSING) { -			compare_height = state.gps_height(); -		} else { -			compare_height = state.height(); -		} - -		if (compare_height != AltosLib.MISSING) { -			int	high_bits = (int) Math.floor (compare_height / 65536.0); - -			height = (high_bits << 16) | (height_16 & 0xffff); +	public AltosTelemetry() { +		this.received_time = System.currentTimeMillis(); +	} -			if (Math.abs(height + 65536 - compare_height) < Math.abs(height - compare_height)) -				height += 65536; -			else if (Math.abs(height - 65536 - compare_height) < Math.abs(height - compare_height)) -				height -= 65536; -		} -		return height; +	public AltosTelemetry(int[] bytes) throws AltosCRCException { +		this(); +		this.bytes = bytes; +		if ((status() & PKT_APPEND_STATUS_1_CRC_OK) == 0) +			throw new AltosCRCException(rssi());  	}  	public static AltosTelemetry parse(String line) throws ParseException, AltosCRCException { @@ -149,7 +129,7 @@ public abstract class AltosTelemetry implements AltosStateUpdate {  			throw new AltosCRCException(AltosParse.parse_int(word[i++]));  		} -		AltosTelemetry telem; +		AltosTelemetry telem = null;  		if (word[i].equals("TELEM")) {  			telem = parse_hex(word[i+1]); diff --git a/altoslib/AltosTelemetryCompanion.java b/altoslib/AltosTelemetryCompanion.java index a97fda2d..c6dfe3eb 100644 --- a/altoslib/AltosTelemetryCompanion.java +++ b/altoslib/AltosTelemetryCompanion.java @@ -16,24 +16,19 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryCompanion extends AltosTelemetryStandard { -	AltosCompanion	companion; - -	static final public int max_channels = 12; - -	public AltosTelemetryCompanion(int[] bytes) { -		super(bytes); +	AltosCompanion	companion() {  		int	channels = uint8(7);  		if (channels > max_channels)  			channels = max_channels; -		companion = new AltosCompanion(channels); +		AltosCompanion companion = new AltosCompanion(channels); -		companion.tick = tick; +		companion.tick = tick();  		companion.board_id = uint8(5);  		companion.update_period = uint8(6); @@ -45,11 +40,17 @@ public class AltosTelemetryCompanion extends AltosTelemetryStandard {  			for (int i = 0; i < channels; i++)  				companion.companion_data[i] = uint16(8 + i * 2);  		} +		return companion;  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	static final public int max_channels = 12; + +	public AltosTelemetryCompanion(int[] bytes) throws AltosCRCException { +		super(bytes); +	} -		state.set_companion(companion); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener); +		listener.set_companion(companion());  	}  } diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java index 6ded5461..ea307442 100644 --- a/altoslib/AltosTelemetryConfiguration.java +++ b/altoslib/AltosTelemetryConfiguration.java @@ -16,47 +16,39 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryConfiguration extends AltosTelemetryStandard { -	int	device_type; -	int	flight; -	int	config_major; -	int	config_minor; -	int	apogee_delay; -	int	main_deploy; -	int	v_batt; -	int	flight_log_max; -	String	callsign; -	String	version; - -	public AltosTelemetryConfiguration(int[] bytes) { -		super(bytes); +	int	device_type() { return uint8(5); } +	int	flight() { return uint16(6); } +	int	config_major() { return uint8(8); } +	int	config_minor() { return uint8(9); } +	int	apogee_delay() { return uint16(10); } +	int	main_deploy() { return uint16(12); } +	int	v_batt() { return uint16(10); } +	int	flight_log_max() { return uint16(14); } +	String	callsign() { return string(16, 8); } +	String	version() { return string(24, 8); } -		device_type    = uint8(5); -		flight         = uint16(6); -		config_major   = uint8(8); -		config_minor   = uint8(9); -		v_batt	       = uint16(10); -		apogee_delay   = uint16(10); -		main_deploy    = uint16(12); -		flight_log_max = uint16(14); -		callsign       = string(16, 8); -		version        = string(24, 8); +	public AltosTelemetryConfiguration(int[] bytes) throws AltosCRCException { +		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); -		state.set_device_type(device_type); -		state.set_flight(flight); -		state.set_config(config_major, config_minor, flight_log_max); -		if (device_type == AltosLib.product_telegps) -			state.set_battery_voltage(AltosConvert.tele_gps_voltage(v_batt)); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener); + +		AltosCalData cal_data = listener.cal_data(); + +		cal_data.set_device_type(device_type()); +		cal_data.set_flight(flight()); +		cal_data.set_config(config_major(), config_minor(), flight_log_max()); +		if (device_type() == AltosLib.product_telegps) +			listener.set_battery_voltage(AltosConvert.tele_gps_voltage(v_batt()));  		else -			state.set_flight_params(apogee_delay, main_deploy); +			cal_data.set_flight_params(apogee_delay() / 100.0, main_deploy()); -		state.set_callsign(callsign); -		state.set_firmware_version(version); +		cal_data.set_callsign(callsign()); +		cal_data.set_firmware_version(version());  	}  } diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java index 9c5f8dae..135b0284 100644 --- a/altoslib/AltosTelemetryFile.java +++ b/altoslib/AltosTelemetryFile.java @@ -16,82 +16,125 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*;  import java.text.*; -class AltosTelemetryIterator implements Iterator<AltosState> { -	AltosState			state; -	Iterator<AltosTelemetry>	telems; -	AltosTelemetry			next; -	boolean				seen; - -	public boolean hasNext() { -		return !seen || telems.hasNext(); -	} - -	public AltosState next() { -		if (seen) { -			AltosState	n = state.clone(); -			AltosTelemetry	t = telems.next(); - -			t.update_state(n); -			state = n; -		} -		seen = true; -		return state; +class AltosTelemetryNullListener extends AltosDataListener { +	public void set_rssi(int rssi, int status) { } +	public void set_received_time(long received_time) { } + +	public void set_acceleration(double accel) { } +	public void set_pressure(double pa) { } +	public void set_thrust(double N) { } + +	public void set_kalman(double height, double speed, double accel) { } + +	public void set_temperature(double deg_c) { } +	public void set_battery_voltage(double volts) { } + +	public void set_apogee_voltage(double volts) { } +	public void set_main_voltage(double volts) { } + +	public void set_gps(AltosGPS gps) { } + +	public void set_orient(double orient) { } +	public void set_gyro(double roll, double pitch, double yaw) { } +	public void set_accel_ground(double along, double across, double through) { } +	public void set_accel(double along, double across, double through) { } +	public void set_mag(double along, double across, double through) { } +	public void set_pyro_voltage(double volts) { } +	public void set_igniter_voltage(double[] voltage) { } +	public void set_pyro_fired(int pyro_mask) { } +	public void set_companion(AltosCompanion companion) { } + +	public boolean cal_data_complete() { +		/* All telemetry packets */ +		AltosCalData cal_data = cal_data(); + +		if (cal_data.serial == AltosLib.MISSING) +			return false; + +		if (cal_data.boost_tick == AltosLib.MISSING) +			return false; + +		/* +		 * TelemetryConfiguration: +		 * +		 * device_type, flight, config version, log max, +		 * flight params, callsign and version +		 */ +		if (cal_data.device_type == AltosLib.MISSING) +			return false; + +		/* +		 * TelemetrySensor or TelemetryMegaData: +		 * +		 * ground_accel, accel+/-, ground pressure +		 */ +		if (cal_data.ground_pressure == AltosLib.MISSING) +			return false; + +		/* +		 * TelemetryLocation +		 */ +		if (AltosLib.has_gps(cal_data.device_type) && cal_data.gps_pad == null) +			return false; + +		return true;  	} -	public void remove () { -	} - -	public AltosTelemetryIterator(AltosState start, Iterator<AltosTelemetry> telems) { -		this.state = start; -		this.telems = telems; -		this.seen = false; +	public AltosTelemetryNullListener(AltosCalData cal_data) { +		super(cal_data);  	}  } -public class AltosTelemetryFile extends AltosStateIterable { +public class AltosTelemetryFile implements AltosRecordSet {  	AltosTelemetryIterable	telems; -	AltosState		start; +	AltosCalData		cal_data;  	public void write_comments(PrintStream out) {  	}  	public void write(PrintStream out) { -  	} -	public AltosTelemetryFile(FileInputStream input) { -		telems = new AltosTelemetryIterable(input); -		start = new AltosState(); - -		/* Find boost tick */ -		AltosState	state = start.clone(); +	/* Construct cal data by walking through the telemetry data until we've found everything available */ +	public AltosCalData cal_data() { +		if (cal_data == null) { +			cal_data = new AltosCalData(); +			AltosTelemetryNullListener l = new AltosTelemetryNullListener(cal_data); -		for (AltosTelemetry telem : telems) { -			telem.update_state(state); -			state.finish_update(); -			if (state.state() != AltosLib.ao_flight_invalid && state.state() >= AltosLib.ao_flight_boost) { -				start.set_boost_tick(state.tick); -				break; +			for (AltosTelemetry telem : telems) { +				telem.provide_data(l); +				if (l.cal_data_complete()) +					break;  			}  		} +		return cal_data;  	} -	public Iterator<AltosState> iterator() { -		AltosState			state = start.clone(); -		Iterator<AltosTelemetry>  	i = telems.iterator(); +	public void capture_series(AltosDataListener listener) { +		AltosCalData	cal_data = cal_data(); + +		cal_data.reset(); +		for (AltosTelemetry telem : telems) { +			int tick = telem.tick(); +			cal_data.set_tick(tick); -		while (i.hasNext() && !state.valid()) { -			AltosTelemetry	t = i.next(); -			t.update_state(state); -			state.finish_update(); +			/* Try to pick up at least one pre-boost value */ +			if (cal_data.time() >= -2) +				telem.provide_data(listener); +			if (listener.state == AltosLib.ao_flight_landed) +				break;  		} -		return new AltosTelemetryIterator(state, i); +		listener.finish(); +	} + +	public AltosTelemetryFile(FileInputStream input) throws IOException { +		telems = new AltosTelemetryIterable(input);  	}  } diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java index 0cba86a3..d3e4ce67 100644 --- a/altoslib/AltosTelemetryIterable.java +++ b/altoslib/AltosTelemetryIterable.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.io.*;  import java.util.*; @@ -67,7 +67,7 @@ public class AltosTelemetryIterable implements Iterable<AltosTelemetry> {  	int index;  	public void add (AltosTelemetry telem) { -		int	t = telem.tick; +		int	t = telem.tick();  		if (!telems.isEmpty()) {  			while (t < tick - 1000)  				t += 65536; @@ -80,29 +80,25 @@ public class AltosTelemetryIterable implements Iterable<AltosTelemetry> {  		return new AltosTelemetryOrderedIterator(telems);  	} -	public AltosTelemetryIterable (FileInputStream input) { +	public AltosTelemetryIterable (FileInputStream input) throws IOException {  		telems = new TreeSet<AltosTelemetryOrdered> ();  		tick = 0;  		index = 0; -		try { -			for (;;) { -				String line = AltosLib.gets(input); -				if (line == null) { +		for (;;) { +			String line = AltosLib.gets(input); +			if (line == null) { +				break; +			} +			try { +				AltosTelemetry telem = AltosTelemetry.parse(line); +				if (telem == null)  					break; -				} -				try { -					AltosTelemetry telem = AltosTelemetry.parse(line); -					if (telem == null) -						break; -					add(telem); -				} catch (ParseException pe) { -					System.out.printf("parse exception %s\n", pe.getMessage()); -				} catch (AltosCRCException ce) { -				} +				add(telem); +			} catch (ParseException pe) { +				System.out.printf("parse exception %s\n", pe.getMessage()); +			} catch (AltosCRCException ce) {  			} -		} catch (IOException io) { -			System.out.printf("io exception\n");  		}  	}  } diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java index 08c52986..027f601e 100644 --- a/altoslib/AltosTelemetryLegacy.java +++ b/altoslib/AltosTelemetryLegacy.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*; @@ -233,6 +233,17 @@ public class AltosTelemetryLegacy extends AltosTelemetry {  	final static String AO_TELEM_SAT_SVID	= "s_v";  	final static String AO_TELEM_SAT_C_N_0	= "s_c"; +	public int	tick; +	public int	serial; +	public int	rssi; +	public int	status; + +	public int tick() { return tick; } +	public int serial() { return serial; } + +	public int rssi() { return rssi; } +	public int status() { return status; } +  	public int	version;  	public String 	callsign;  	public int	flight; @@ -271,7 +282,6 @@ public class AltosTelemetryLegacy extends AltosTelemetry {  		flight = map.get_int(AO_TELEM_FLIGHT, AltosLib.MISSING);  		rssi = map.get_int(AO_TELEM_RSSI, AltosLib.MISSING);  		state = AltosLib.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, AltosLib.MISSING); @@ -420,7 +430,6 @@ public class AltosTelemetryLegacy extends AltosTelemetry {  	 * Given a hex dump of a legacy telemetry line, construct an AltosRecordTM from that  	 */ -	int[]	bytes;  	int	adjust;  	/* @@ -452,8 +461,9 @@ public class AltosTelemetryLegacy extends AltosTelemetry {  	static final int AO_GPS_DATE_VALID	= (1 << 6);  	static final int AO_GPS_COURSE_VALID	= (1 << 7); -	public AltosTelemetryLegacy(int[] in_bytes) { -		bytes = in_bytes; +	public AltosTelemetryLegacy(int[] in_bytes) throws AltosCRCException { +		super(in_bytes); +  		version = 4;  		adjust = 0; @@ -463,6 +473,7 @@ public class AltosTelemetryLegacy extends AltosTelemetry {  		} else  			serial = uint16(0); +		rssi = super.rssi();  		callsign = string(62, 8);  		flight = uint16(2);  		state = uint8(4); @@ -537,23 +548,26 @@ public class AltosTelemetryLegacy extends AltosTelemetry {  		}  	} -	public void update_state(AltosState state) { -		state.set_tick(tick); -		state.set_state(this.state); -		state.set_flight(flight); -		state.set_serial(serial); -		state.set_rssi(rssi, status); +	public void provide_data(AltosDataListener listener) { +		listener.set_serial(serial); +		listener.set_tick(tick); +		listener.set_state(this.state); +		listener.set_flight(flight); +		listener.set_rssi(rssi, status); + +		listener.set_pressure(AltosConvert.barometer_to_pressure(pres)); + +		AltosCalData cal_data = listener.cal_data(); -		state.set_pressure(AltosConvert.barometer_to_pressure(pres)); -		state.set_accel_g(accel_plus_g, accel_minus_g); -		state.set_accel(accel); +		cal_data.set_accel_plus_minus(accel_plus_g, accel_minus_g); +		listener.set_acceleration(cal_data.acceleration(accel));  		if (kalman_height != AltosLib.MISSING) -			state.set_kalman(kalman_height, kalman_speed, kalman_acceleration); -		state.set_temperature(AltosConvert.thermometer_to_temperature(temp)); -		state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); -		state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(apogee)); -		state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(main)); +			listener.set_kalman(kalman_height, kalman_speed, kalman_acceleration); +		listener.set_temperature(AltosConvert.thermometer_to_temperature(temp)); +		listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); +		listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(apogee)); +		listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(main));  		if (gps != null) -			state.set_gps(gps, gps_sequence); +			listener.set_gps(gps);  	}  } diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java index 11995640..f4366e33 100644 --- a/altoslib/AltosTelemetryLocation.java +++ b/altoslib/AltosTelemetryLocation.java @@ -16,81 +16,73 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryLocation extends AltosTelemetryStandard { -	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; +	int	flags() { return uint8(5); } +	int	altitude() { +		if ((mode() & AO_GPS_MODE_ALTITUDE_24) != 0) +			return (int8(31) << 16) | uint16(6); +		else +			return int16(6); +	} +	int	latitude() { return uint32(8); } +	int	longitude() { return uint32(12); } +	int	year() { return uint8(16); } +	int	month() { return uint8(17); } +	int	day() { return uint8(18); } +	int	hour() { return uint8(19); } +	int	minute() { return uint8(20); } +	int	second() { return uint8(21); } +	int	pdop() { return uint8(22); } +	int	hdop() { return uint8(23); } +	int	vdop() { return uint8(24); } +	int	mode() { return uint8(25); } +	int	ground_speed() { return uint16(26); } +	int	climb_rate() { return int16(28); } +	int	course() { return uint8(30); }  	public static final int	AO_GPS_MODE_ALTITUDE_24 = (1 << 0);	/* Reports 24-bits of altitude */ -	public AltosTelemetryLocation(int[] bytes) { +	public AltosTelemetryLocation(int[] bytes) throws AltosCRCException {  		super(bytes); +	} -		flags          = uint8(5); -		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 void provide_data(AltosDataListener listener) { +		super.provide_data(listener); -		if ((mode & AO_GPS_MODE_ALTITUDE_24) != 0) { -			altitude = (int8(31) << 16) | uint16(6); -		} else -			altitude = int16(6); -	} +		AltosCalData	cal_data = listener.cal_data(); -	public void update_state(AltosState state) { -		super.update_state(state); -		AltosGPS	gps = state.make_temp_gps(false); +		AltosGPS	gps = cal_data.make_temp_gps(tick(), false); +		int flags = flags();  		gps.nsat = flags & 0xf;  		gps.locked = (flags & (1 << 4)) != 0;  		gps.connected = (flags & (1 << 5)) != 0; +		gps.pdop = pdop() / 10.0; +		gps.hdop = hdop() / 10.0; +		gps.vdop = vdop() / 10.0;  		if (gps.locked) { -			gps.lat = latitude * 1.0e-7; -			gps.lon = longitude * 1.0e-7; -			gps.alt = altitude; -			gps.year = 2000 + year; -			gps.month = month; -			gps.day = day; -			gps.hour = hour; -			gps.minute = minute; -			gps.second = second; -			gps.ground_speed = ground_speed * 1.0e-2; -			gps.course = course * 2; -			gps.climb_rate = climb_rate * 1.0e-2; -			gps.pdop = pdop / 10.0; -			gps.hdop = hdop / 10.0; -			gps.vdop = vdop / 10.0; +			gps.lat = latitude() * 1.0e-7; +			gps.lon = longitude() * 1.0e-7; +			gps.alt = altitude(); +			gps.year = 2000 + year(); +			gps.month = month(); +			gps.day = day(); +			gps.hour = hour(); +			gps.minute = minute(); +			gps.second = second(); +			gps.ground_speed = ground_speed() * 1.0e-2; +			gps.course = course() * 2; +			gps.climb_rate = climb_rate() * 1.0e-2; + +			if (gps.nsat >= 4) +				cal_data.set_gps(gps);  		} -		state.set_temp_gps(); +		listener.set_gps(gps); +		cal_data.set_gps(gps); +		cal_data.reset_temp_gps();  	}  } diff --git a/altoslib/AltosTelemetryMap.java b/altoslib/AltosTelemetryMap.java index c8185434..a7ddc684 100644 --- a/altoslib/AltosTelemetryMap.java +++ b/altoslib/AltosTelemetryMap.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*;  import java.util.HashMap; diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java index 6ea5ec89..7ef9c637 100644 --- a/altoslib/AltosTelemetryMegaData.java +++ b/altoslib/AltosTelemetryMegaData.java @@ -16,78 +16,58 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryMegaData extends AltosTelemetryStandard { -	int	state; -	int	v_batt; -	int	v_pyro; -	int	sense[]; +	int	state() { return uint8(5); } -	int	ground_pres; -	int	ground_accel; -	int	accel_plus_g; -	int	accel_minus_g; +	int	v_batt() { return int16(6); } +	int	v_pyro() { return int16(8); } +	int	sense(int i) { int v = uint8(10+i); return v << 4 | v >> 8; } -	int	acceleration; -	int	speed; -	int	height_16; +	int	ground_pres() { return int32(16); } +	int	ground_accel() { return int16(20); } +	int	accel_plus_g() { return int16(22); } +	int	accel_minus_g() { return int16(24);} -	public AltosTelemetryMegaData(int[] bytes) { -		super(bytes); - -		state = uint8(5); - -		v_batt = int16(6); -		v_pyro = int16(8); - -		sense = new int[6]; - -		for (int i = 0; i < 6; i++) { -			sense[i] = uint8(10 + i) << 4; -			sense[i] |= sense[i] >> 8; -		} +	int	acceleration() { return int16(26); } +	int	speed() { return int16(28); } +	int	height_16() { return int16(30); } -		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_16 = int16(30); +	public AltosTelemetryMegaData(int[] bytes) throws AltosCRCException { +		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener); -		state.set_state(this.state); +		listener.set_state(state()); -		state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt)); -		state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro)); +		listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); +		listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro())); -		state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense[4])); -		state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense[5])); +		listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(4))); +		listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(5)));  		double voltages[] = new double[4];  		for (int i = 0; i < 4; i++) -			voltages[i] = AltosConvert.mega_pyro_voltage(sense[i]); +			voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); + +		listener.set_igniter_voltage(voltages); -		state.set_ignitor_voltage(voltages); +		AltosCalData cal_data = listener.cal_data(); -		state.set_ground_accel(ground_accel); -		state.set_ground_pressure(ground_pres); -		state.set_accel_g(accel_plus_g, accel_minus_g); +		cal_data.set_ground_accel(ground_accel()); +		cal_data.set_ground_pressure(ground_pres()); +		cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g());  		/* Fill in the high bits of height from recent GPS  		 * data if available, otherwise guess using the  		 * previous kalman height  		 */ -		state.set_kalman(extend_height(state, height_16), -				 speed/16.0, acceleration / 16.0); +		listener.set_kalman(height_16(), speed()/16.0, acceleration() / 16.0);  	}  } diff --git a/altoslib/AltosTelemetryMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java index 2dfc455a..4c64b554 100644 --- a/altoslib/AltosTelemetryMegaSensor.java +++ b/altoslib/AltosTelemetryMegaSensor.java @@ -16,64 +16,68 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryMegaSensor extends AltosTelemetryStandard { -	int	accel; -	int	pres; -	int	temp; +	int	orient() { return int8(5); } -	int	accel_x; -	int	accel_y; -	int	accel_z; +	int	accel() { return int16(6); } +	int	pres() { return int32(8); } +	int	temp() { return int16(12); } -	int	gyro_x; -	int	gyro_y; -	int	gyro_z; +	int	accel_x() { return int16(14); } +	int	accel_y() { return int16(16); } +	int	accel_z() { return int16(18); } -	int	mag_x; -	int	mag_y; -	int	mag_z; +	int	gyro_x() { return int16(20); } +	int	gyro_y() { return int16(22); } +	int	gyro_z() { return int16(24); } -	int	orient; +	int	mag_x() { return int16(26); } +	int	mag_z() { return int16(28); } +	int	mag_y() { return int16(30); } -	public AltosTelemetryMegaSensor(int[] bytes) { +	public AltosTelemetryMegaSensor(int[] bytes) throws AltosCRCException {  		super(bytes); +	} -		orient	      = int8(5); -		accel         = int16(6); -		pres          = int32(8); -		temp          = int16(12); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener); -		accel_x	      = int16(14); -		accel_y	      = int16(16); -		accel_z	      = int16(18); +		AltosCalData cal_data = listener.cal_data(); -		gyro_x	      = int16(20); -		gyro_y	      = int16(22); -		gyro_z	      = int16(24); +		listener.set_acceleration(cal_data.acceleration(accel())); +		listener.set_pressure(pres()); +		listener.set_temperature(temp() / 100.0); -		mag_x	      = int16(26); -		mag_y	      = int16(28); -		mag_z	      = int16(30); -	} +		listener.set_orient(orient()); -	public void update_state(AltosState state) { -		super.update_state(state); +		/* XXX we have no calibration data for these values */ -		state.set_accel(accel); -		state.set_pressure(pres); -		state.set_temperature(temp / 100.0); +		if (cal_data.accel_zero_along == AltosLib.MISSING) +			cal_data.set_accel_zero(0, 0, 0); +		if (cal_data.gyro_zero_roll == AltosLib.MISSING) +			cal_data.set_gyro_zero(0, 0, 0); -		state.set_orient(orient); +		int	accel_along = accel_y(); +		int	accel_across = accel_x(); +		int	accel_through = accel_z(); +		int	gyro_roll = gyro_y(); +		int	gyro_pitch = gyro_x(); +		int	gyro_yaw = gyro_z(); -		state.set_imu(new AltosIMU(accel_y,	/* along */ -					   accel_x,	/* across */ -					   accel_z,	/* through */ -					   gyro_y,	/* along */ -					   gyro_x,	/* across */ -					   gyro_z));	/* through */ +		int	mag_along = mag_y(); +		int	mag_across = mag_x(); +		int	mag_through = mag_z(); -		state.set_mag(new AltosMag(mag_x, mag_y, mag_z)); +		listener.set_accel(cal_data.accel_along(accel_along), +				   cal_data.accel_across(accel_across), +				   cal_data.accel_through(accel_through)); +		listener.set_gyro(cal_data.gyro_roll(gyro_roll), +				  cal_data.gyro_pitch(gyro_pitch), +				  cal_data.gyro_yaw(gyro_yaw)); +		listener.set_mag(cal_data.mag_along(mag_along), +				 cal_data.mag_across(mag_across), +				 cal_data.mag_through(mag_through));  	}  } diff --git a/altoslib/AltosTelemetryMetrumData.java b/altoslib/AltosTelemetryMetrumData.java index 53a10cc4..8cd09b41 100644 --- a/altoslib/AltosTelemetryMetrumData.java +++ b/altoslib/AltosTelemetryMetrumData.java @@ -16,28 +16,23 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryMetrumData extends AltosTelemetryStandard { -	int	ground_pres; -	int	ground_accel; -	int	accel_plus_g; -	int	accel_minus_g; +	int	ground_pres() { return int32(8); } +	int	ground_accel() { return int16(12); } +	int	accel_plus_g() { return int16(14); } +	int	accel_minus_g() { return int16(16); } -	public AltosTelemetryMetrumData(int[] bytes) { +	public AltosTelemetryMetrumData(int[] bytes) throws AltosCRCException {  		super(bytes); - -		ground_pres = int32(8); -		ground_accel = int16(12); -		accel_plus_g = int16(14); -		accel_minus_g = int16(16);  	} -	public void update_state(AltosState state) { -		state.set_ground_accel(ground_accel); -		state.set_accel_g(accel_plus_g, accel_minus_g); -		state.set_ground_pressure(ground_pres); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		cal_data.set_ground_accel(ground_accel()); +		cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); +		cal_data.set_ground_pressure(ground_pres());  	}  } diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java index e15043b4..79d3a499 100644 --- a/altoslib/AltosTelemetryMetrumSensor.java +++ b/altoslib/AltosTelemetryMetrumSensor.java @@ -16,56 +16,42 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard { -	int	state; +	int	state() { return uint8(5); } -	int	accel; -	int	pres; -	int	temp; +	int	accel() { return int16(6); } +	int	pres() { return int32(8); } +	int	temp() { return int16(12); } -	int	acceleration; -	int	speed; -	int	height_16; +	int	acceleration() { return int16(14); } +	int	speed() { return int16(16); } +	int	height_16() { return int16(18); } -	int	v_batt; -	int	sense_a; -	int	sense_m; +	int	v_batt() { return int16(20); } +	int	sense_a() { return int16(22); } +	int	sense_m() { return int16(24); } -	public AltosTelemetryMetrumSensor(int[] bytes) { +	public AltosTelemetryMetrumSensor(int[] bytes) throws AltosCRCException {  		super(bytes); - -		state	      = int8(5); -		accel         = int16(6); -		pres          = int32(8); -		temp          = int16(12); - -		acceleration  = int16(14); -		speed         = int16(16); -		height_16     = int16(18); - -		v_batt        = int16(20); -		sense_a       = int16(22); -		sense_m       = int16(24);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener); -		state.set_state(this.state); +		listener.set_state(state()); -		state.set_accel(accel); -		state.set_pressure(pres); -		state.set_temperature(temp/100.0); +		listener.set_acceleration(listener.cal_data().acceleration(accel())); +		listener.set_pressure(pres()); +		listener.set_temperature(temp()/100.0); -		state.set_kalman(extend_height(state, height_16), -				 speed/16.0, acceleration/16.0); +		listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); -		state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt)); +		listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); -		state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a)); -		state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m)); +		listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); +		listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));  	}  } diff --git a/altoslib/AltosTelemetryMini2.java b/altoslib/AltosTelemetryMini2.java index 50ec504d..3ea287ac 100644 --- a/altoslib/AltosTelemetryMini2.java +++ b/altoslib/AltosTelemetryMini2.java @@ -16,58 +16,46 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryMini2 extends AltosTelemetryStandard { -	int	state; -	int	v_batt; -	int	sense_a; -	int	sense_m; +	int	state() { return uint8(5); } -	int	pres; -	int	temp; +	int	v_batt() { return int16(6); } +	int	sense_a() { return int16(8); } +	int	sense_m() { return int16(10); } -	int	acceleration; -	int	speed; -	int	height; +	int	pres() { return int32(12); } +	int	temp() { return int16(16); } -	int	ground_pres; +	int	acceleration() { return int16(18); } +	int	speed() { return int16(20); } +	int	height() { return int16(22); } -	public AltosTelemetryMini2(int[] bytes) { -		super(bytes); - -		state	      = int8(5); - -		v_batt        = int16(6); -		sense_a       = int16(8); -		sense_m       = int16(10); - -		pres          = int32(12); -		temp          = int16(16); +	int	ground_pres() { return int32(24); } -		acceleration  = int16(18); -		speed         = int16(20); -		height        = int16(22); - -		ground_pres   = int32(24); +	public AltosTelemetryMini2(int[] bytes) throws AltosCRCException { +		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener); + +		listener.set_state(state()); -		state.set_state(this.state); +		listener.set_battery_voltage(AltosConvert.tele_mini_2_voltage(v_batt())); +		listener.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sense_a())); +		listener.set_main_voltage(AltosConvert.tele_mini_2_voltage(sense_m())); -		state.set_battery_voltage(AltosConvert.tele_mini_2_voltage(v_batt)); -		state.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sense_a)); -		state.set_main_voltage(AltosConvert.tele_mini_2_voltage(sense_m)); +		AltosCalData	cal_data = listener.cal_data(); -		state.set_ground_pressure(ground_pres); +		cal_data.set_ground_pressure(ground_pres()); -		state.set_pressure(pres); -		state.set_temperature(temp/100.0); +		listener.set_pressure(pres()); +		listener.set_temperature(temp()/100.0); -		state.set_kalman(height, speed/16.0, acceleration/16.0); +		listener.set_kalman(height(), speed()/16.0, acceleration()/16.0);  	}  } diff --git a/altoslib/AltosTelemetryMini3.java b/altoslib/AltosTelemetryMini3.java index 21f8c485..c66f8e61 100644 --- a/altoslib/AltosTelemetryMini3.java +++ b/altoslib/AltosTelemetryMini3.java @@ -16,61 +16,45 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryMini3 extends AltosTelemetryStandard { -	int	state; +	int	state() { return uint8(5); } -	int	v_batt; -	int	sense_a; -	int	sense_m; +	int	v_batt() { return int16(6); } +	int	sense_a() { return int16(8); } +	int	sense_m() { return int16(10); } -	int	pres; -	int	temp; +	int	pres() { return int32(12); } +	int	temp() { return int16(16); } -	int	acceleration; -	int	speed; -	int	height_16; +	int	acceleration() { return int16(18); } +	int	speed() { return int16(20); } +	int	height_16() { return int16(22); } -	int	ground_pres; +	int	ground_pres() { return int32(24); } -	public AltosTelemetryMini3(int[] bytes) { +	public AltosTelemetryMini3(int[] bytes) throws AltosCRCException {  		super(bytes); - -		state         = int8(5); - -		v_batt        = int16(6); -		sense_a       = int16(8); -		sense_m       = int16(10); - -		pres          = int32(12); -		temp          = int16(16); - -		acceleration  = int16(18); -		speed         = int16(20); -		height_16     = int16(22); - -		ground_pres   = int32(24);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener); -		state.set_state(this.state); +		listener.set_state(state()); -		state.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(v_batt)); +		listener.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(v_batt())); -		state.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_a)); -		state.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_m)); +		listener.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_a())); +		listener.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_m())); -		state.set_pressure(pres); -		state.set_temperature(temp/100.0); +		listener.cal_data().set_ground_pressure(ground_pres()); -		state.set_kalman(extend_height(state, height_16), -				 speed/16.0, acceleration/16.0); +		listener.set_pressure(pres()); +		listener.set_temperature(temp()/100.0); -		state.set_ground_pressure(ground_pres); +		listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0);  	}  } diff --git a/altoslib/AltosTelemetryRaw.java b/altoslib/AltosTelemetryRaw.java index 339043a6..f2108d68 100644 --- a/altoslib/AltosTelemetryRaw.java +++ b/altoslib/AltosTelemetryRaw.java @@ -16,14 +16,14 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetryRaw extends AltosTelemetryStandard { -	public AltosTelemetryRaw(int[] bytes) { +	public AltosTelemetryRaw(int[] bytes) throws AltosCRCException {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener);  	}  } diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 6a93c2c3..26fe4f26 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -16,19 +16,20 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*;  import java.io.*;  import java.util.concurrent.*;  public class AltosTelemetryReader extends AltosFlightReader { -	AltosLink	link; -	AltosLog	log; -	double		frequency; -	int		telemetry; -	int		telemetry_rate; -	AltosState	state = null; +	AltosLink		link; +	AltosLog		log; +	double			frequency; +	int			telemetry; +	int			telemetry_rate; +	private AltosState	state = null; +	private AltosCalData	cal_data = null;  	LinkedBlockingQueue<AltosLine> telem; @@ -40,14 +41,22 @@ public class AltosTelemetryReader extends AltosFlightReader {  				throw new IOException("IO error");  		} while (!link.get_monitor());  		AltosTelemetry	telem = AltosTelemetry.parse(l.line); -		if (state == null) -			state = new AltosState(); -		else -			state = state.clone(); -		telem.update_state(state); +		if (state == null) { +			System.out.printf("Make state\n"); +			state = new AltosState(cal_data()); +		} +		telem.provide_data(state);  		return state;  	} +	public AltosCalData cal_data() { +		if (cal_data == null) { +			System.out.printf("Make cal data\n"); +			cal_data = new AltosCalData(); +		} +		return cal_data; +	} +  	public void flush() {  		telem.clear();  	} @@ -55,6 +64,7 @@ public class AltosTelemetryReader extends AltosFlightReader {  	public void reset() {  		flush();  		state = null; +		cal_data = null;  	}  	public void close(boolean interrupted) { diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java index 6897f0e6..60bc4a51 100644 --- a/altoslib/AltosTelemetrySatellite.java +++ b/altoslib/AltosTelemetrySatellite.java @@ -16,16 +16,15 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetrySatellite extends AltosTelemetryStandard { -	int		channels; -	AltosGPSSat[]	sats; +	int		channels() { return uint8(5); } -	public AltosTelemetrySatellite(int[] bytes) { -		super(bytes); +	AltosGPSSat[]	sats() { +		int 		channels = channels(); +		AltosGPSSat[]	sats = null; -		channels = uint8(5);  		if (channels > 12)  			channels = 12;  		if (channels == 0) @@ -38,14 +37,22 @@ public class AltosTelemetrySatellite extends AltosTelemetryStandard {  				sats[i] = new AltosGPSSat(svid, c_n_1);  			}  		} +		return sats;  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public AltosTelemetrySatellite(int[] bytes) throws AltosCRCException { +		super(bytes); +	} + +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener); + +		AltosCalData	cal_data = listener.cal_data(); -		AltosGPS	gps = state.make_temp_gps(true); +		AltosGPS	gps = cal_data.make_temp_gps(tick(), true); -		gps.cc_gps_sat = sats; -		state.set_temp_gps(); +		gps.cc_gps_sat = sats(); +		listener.set_gps(gps); +		cal_data.reset_temp_gps();  	}  } diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java index 3c3e6a01..dc8efa9b 100644 --- a/altoslib/AltosTelemetrySensor.java +++ b/altoslib/AltosTelemetrySensor.java @@ -16,66 +16,52 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTelemetrySensor extends AltosTelemetryStandard { -	int	state; -	int	accel; -	int	pres; -	int	temp; -	int	v_batt; -	int	sense_d; -	int	sense_m; +	int	state() { return uint8(5); } +	int	accel() { return int16(6); } +	int	pres() { return int16(8); } +	int	temp() { return int16(10); } +	int	v_batt() { return int16(12); } +	int	sense_d() { return int16(14); } +	int	sense_m() { return int16(16); } -	int	acceleration; -	int	speed; -	int	height; +	int	acceleration() { return int16(18); } +	int	speed() { return int16(20); } +	int	height_16() { return int16(22); } -	int	ground_accel; -	int	ground_pres; -	int	accel_plus_g; -	int	accel_minus_g; +	int	ground_accel() { return int16(24); } +	int	ground_pres() { return int16(26); } +	int	accel_plus_g() { return int16(28); } +	int	accel_minus_g() { return int16(30); } -	public AltosTelemetrySensor(int[] bytes) { +	public AltosTelemetrySensor(int[] bytes) throws AltosCRCException {  		super(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); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener); -		ground_pres   = int16(24); -		ground_accel  = int16(26); -		accel_plus_g  = int16(28); -		accel_minus_g = int16(30); -	} +		listener.set_state(state()); -	public void update_state(AltosState state) { -		super.update_state(state); +		AltosCalData	cal_data = listener.cal_data(); -		state.set_state(this.state); -		if (type == packet_type_TM_sensor) { -			state.set_ground_accel(ground_accel); -			state.set_accel_g(accel_plus_g, accel_minus_g); -			state.set_accel(accel); +		if (type() == packet_type_TM_sensor) { +			cal_data.set_ground_accel(ground_accel()); +			cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); +			listener.set_acceleration(cal_data.acceleration(accel()));  		} -		state.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres)); -		state.set_pressure(AltosConvert.barometer_to_pressure(pres)); -		state.set_temperature(AltosConvert.thermometer_to_temperature(temp)); -		state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt)); -		if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) { -			state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sense_d)); -			state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sense_m)); +		cal_data.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres())); +		listener.set_pressure(AltosConvert.barometer_to_pressure(pres())); +		listener.set_temperature(AltosConvert.thermometer_to_temperature(temp())); +		listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt())); +		if (type() == packet_type_TM_sensor || type() == packet_type_Tm_sensor) { +			listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(sense_d())); +			listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(sense_m()));  		} -		state.set_kalman(height, speed/16.0, acceleration / 16.0); +		listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0);  	}  } diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java index 35d315c7..2a1c9365 100644 --- a/altoslib/AltosTelemetryStandard.java +++ b/altoslib/AltosTelemetryStandard.java @@ -16,12 +16,9 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public abstract class AltosTelemetryStandard extends AltosTelemetry { -	int[]	bytes; -	int	type; -  	public int int8(int off) {  		return AltosLib.int8(bytes, off + 1);  	} @@ -50,10 +47,16 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry {  		return AltosLib.string(bytes, off + 1, l);  	} -	public static AltosTelemetry parse_hex(int[] bytes) { -		int	type = AltosLib.uint8(bytes, 4 + 1); +	public int type() { return uint8(4); } + +	public int serial() { return uint16(0); } + +	public int tick() { return uint16(2); } +	public static AltosTelemetry parse_hex(int[] bytes) throws AltosCRCException {  		AltosTelemetry	telem; + +		int type = AltosLib.uint8(bytes, 4+1);  		switch (type) {  		case packet_type_TM_sensor:  		case packet_type_Tm_sensor: @@ -97,15 +100,11 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry {  		return telem;  	} -	public AltosTelemetryStandard(int[] bytes) { -		this.bytes = bytes; - -		serial = uint16(0); -		tick   = uint16(2); -		type   = uint8(4); +	public AltosTelemetryStandard(int[] bytes) throws AltosCRCException { +		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener) { +		super.provide_data(listener);  	}  } diff --git a/altoslib/AltosTemperature.java b/altoslib/AltosTemperature.java index d63e81d1..efc6d5e1 100644 --- a/altoslib/AltosTemperature.java +++ b/altoslib/AltosTemperature.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosTemperature extends AltosUnits { diff --git a/altoslib/AltosTime.java b/altoslib/AltosTime.java new file mode 100644 index 00000000..5c6ab037 --- /dev/null +++ b/altoslib/AltosTime.java @@ -0,0 +1,33 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosTime extends AltosUnits { +	public double value(double v, boolean imperial_units) { return v; } + +	public double inverse(double v, boolean imperial_unis) { return v; } + +	public String show_units(boolean imperial_units) { return "s"; } + +	public String say_units(boolean imperial_units) { return "seconds"; } + +	public int show_fraction(int width, boolean imperial_units) { +		if (width < 5) +			return 0; +		return width - 5; +	} + +	public int say_fraction(boolean imperial_units) { return 0; } +} diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java new file mode 100644 index 00000000..b3c432fc --- /dev/null +++ b/altoslib/AltosTimeSeries.java @@ -0,0 +1,307 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +import java.util.*; + +public class AltosTimeSeries implements Iterable<AltosTimeValue>, Comparable<AltosTimeSeries> { +	public String			label; +	public AltosUnits		units; +	ArrayList<AltosTimeValue>	values; + +	public int compareTo(AltosTimeSeries other) { +		return label.compareTo(other.label); +	} + +	public void add(AltosTimeValue tv) { +		values.add(tv); +	} + +	public void add(double time, double value) { +		add(new AltosTimeValue(time, value)); +	} + +	public AltosTimeValue get(int i) { +		return values.get(i); +	} + +	private double lerp(AltosTimeValue v0, AltosTimeValue v1, double t) { +		/* degenerate case */ +		if (v0.time == v1.time) +			return (v0.value + v1.value) / 2; + +		return (v0.value * (v1.time - t) + v1.value * (t - v0.time)) / (v1.time - v0.time); +	} + +	private int after_index(double time) { +		int	lo = 0; +		int	hi = values.size() - 1; + +		while (lo <= hi) { +			int mid = (lo + hi) / 2; + +			if (values.get(mid).time < time) +				lo = mid + 1; +			else +				hi = mid - 1; +		} +		return lo; +	} + +	/* Compute a value for an arbitrary time */ +	public double value(double time) { +		int after = after_index(time); +		double ret; + +		if (after == 0) +			ret = values.get(0).value; +		else if (after == values.size()) +			ret = values.get(after - 1).value; +		else { +			AltosTimeValue b = values.get(after-1); +			AltosTimeValue a = values.get(after); +			ret = lerp(b, a, time); +		} +		return ret; +	} + +	/* Find the value just before an arbitrary time */ +	public double value_before(double time) { +		int after = after_index(time); + +		if (after == 0) +			return values.get(0).value; +		return values.get(after-1).value; +	} + +	/* Find the value just after an arbitrary time */ +	public double value_after(double time) { +		int after = after_index(time); + +		if (after == values.size()) +			return values.get(after-1).value; +		return values.get(after).value; +	} + +	public double time_of(double value) { +		double	last = AltosLib.MISSING; +		for (AltosTimeValue v : values) { +			if (v.value >= value) +				return v.time; +			last = v.time; +		} +		return last; +	} + +	public int size() { +		return values.size(); +	} + +	public Iterator<AltosTimeValue> iterator() { +		return values.iterator(); +	} + +	public AltosTimeValue max() { +		AltosTimeValue max = null; +		for (AltosTimeValue tv : values) +			if (max == null || tv.value > max.value) +				max = tv; +		return max; +	} + +	public AltosTimeValue max(double start_time, double end_time) { +		AltosTimeValue max = null; +		for (AltosTimeValue tv : values) { +			if (start_time <= tv.time && tv.time <= end_time) +				if (max == null || tv.value > max.value) +					max = tv; +		} +		return max; +	} + +	public AltosTimeValue min() { +		AltosTimeValue min = null; +		for (AltosTimeValue tv : values) { +			if (min == null || tv.value < min.value) +				min = tv; +		} +		return min; +	} + +	public AltosTimeValue min(double start_time, double end_time) { +		AltosTimeValue min = null; +		for (AltosTimeValue tv : values) { +			if (start_time <= tv.time && tv.time <= end_time) +				if (min == null || tv.value < min.value) +					min = tv; +		} +		return min; +	} + +	public AltosTimeValue first() { +		return values.get(0); +	} + +	public AltosTimeValue last() { +		return values.get(values.size() - 1); +	} + +	public double average() { +		double total_value = 0; +		double total_time = 0; +		AltosTimeValue prev = null; +		for (AltosTimeValue tv : values) { +			if (prev != null) { +				total_value += (tv.value + prev.value) / 2 * (tv.time - prev.time); +				total_time += (tv.time - prev.time); +			} +			prev = tv; +		} +		if (total_time == 0) +			return AltosLib.MISSING; +		return total_value / total_time; +	} + +	public double average(double start_time, double end_time) { +		double total_value = 0; +		double total_time = 0; +		AltosTimeValue prev = null; +		for (AltosTimeValue tv : values) { +			if (start_time <= tv.time && tv.time <= end_time) { +				if (prev != null) { +					total_value += (tv.value + prev.value) / 2 * (tv.time - start_time); +					total_time += (tv.time - start_time); +				} +				start_time = tv.time; +			} +			prev = tv; +		} +		if (total_time == 0) +			return AltosLib.MISSING; +		return total_value / total_time; +	} + +	public AltosTimeSeries integrate(AltosTimeSeries integral) { +		double	value = 0.0; +		double	pvalue = 0.0; +		double 	time = 0.0; +		boolean start = true; + +		for (AltosTimeValue v : values) { +			if (start) { +				value = 0.0; +				start = false; +			} else { +				value += (pvalue + v.value) / 2.0 * (v.time - time); +			} +			pvalue = v.value; +			time = v.time; +			integral.add(time, value); + +		} +		return integral; +	} + +	public AltosTimeSeries differentiate(AltosTimeSeries diff) { +		double value = 0.0; +		double time = 0.0; +		boolean start = true; + +		for (AltosTimeValue v: values) { +			if (start) { +				value = v.value; +				time = v.time; +				start = false; +			} else { +				double	dx = v.time - time; +				double	dy = v.value - value; + +				if (dx != 0) +					diff.add(time, dy/dx); + +				time = v.time; +				value = v.value; +			} +		} +		return diff; +	} + +	private int find_left(int i, double dt) { +		int j; +		double t = values.get(i).time - dt; +		for (j = i; j >= 0; j--)	{ +			if (values.get(j).time < t) +				break; +		} +		return j + 1; + +	} + +	private int find_right(int i, double dt) { +		int j; +		double t = values.get(i).time + dt; +		for (j = i; j < values.size(); j++) { +			if (values.get(j).time > t) +				break; +		} +		return j - 1; + +	} + +	private double filter_coeff(double dist, double width) { +		double ratio = dist / (width / 2); + +		return Math.cos(ratio * Math.PI / 2); +	} + +	public AltosTimeSeries filter(AltosTimeSeries f, double width) { +		double	half_width = width/2; +		for (int i = 0; i < values.size(); i++) { +			double	center_time = values.get(i).time; +			double	left_time = center_time - half_width; +			double	right_time = center_time + half_width; +			double	total_coeff = 0.0; +			double	total_value = 0.0; + +			int	left = find_left(i, half_width); +			int	right = find_right(i, half_width); + +			for (int j = left; j <= right; j++) { +				double	j_time = values.get(j).time; + +				if (left_time <= j_time && j_time <= right_time) { +					double	j_left = j == left ? left_time : values.get(j-1).time; +					double	j_right = j == right ? right_time : values.get(j+1).time; +					double	interval = (j_right - j_left) / 2.0; +					double	coeff = filter_coeff(j_time - center_time, width) * interval; +					double	value = values.get(j).value; +					double	partial = value * coeff; + +					total_coeff += coeff; +					total_value += partial; +				} +			} +			if (total_coeff != 0.0) +				f.add(center_time, total_value / total_coeff); +		} +		return f; +	} + +	public AltosTimeSeries(String label, AltosUnits units) { +		this.label = label; +		this.units = units; +		this.values = new ArrayList<AltosTimeValue>(); +	} +} diff --git a/altoslib/AltosTimeValue.java b/altoslib/AltosTimeValue.java new file mode 100644 index 00000000..298ac7f0 --- /dev/null +++ b/altoslib/AltosTimeValue.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosTimeValue { +	public double	time; +	public double	value; + +	public AltosTimeValue(double time, double value) { +		this.time = time; +		this.value = value; +	} +} diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java index 717a106a..e1194487 100644 --- a/altoslib/AltosUnits.java +++ b/altoslib/AltosUnits.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*; @@ -41,6 +41,10 @@ public abstract class AltosUnits {  	public abstract double inverse(double v, boolean imperial_units); +	public String string_value(double v, boolean imperial_units) { +		return new Double(value(v, imperial_units)).toString(); +	} +  	public abstract String show_units(boolean imperial_units);  	public abstract String say_units(boolean imperial_units); @@ -113,6 +117,10 @@ public abstract class AltosUnits {  		return say_units(v, AltosConvert.imperial_units);  	} +	public String string_value(double v) { +		return string_value(v, AltosConvert.imperial_units); +	} +  	/* Parsing functions. Use the first range of the type */  	public String parse_units(boolean imperial_units) {  		return first_range(imperial_units).show_units; diff --git a/altoslib/AltosUnitsListener.java b/altoslib/AltosUnitsListener.java index e094810c..1f06afbf 100644 --- a/altoslib/AltosUnitsListener.java +++ b/altoslib/AltosUnitsListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosUnitsListener {  	public void units_changed(boolean imperial_units); diff --git a/altoslib/AltosUnitsRange.java b/altoslib/AltosUnitsRange.java index 9f56001d..6bf0d91f 100644 --- a/altoslib/AltosUnitsRange.java +++ b/altoslib/AltosUnitsRange.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import java.text.*; diff --git a/altoslib/AltosUnknownProduct.java b/altoslib/AltosUnknownProduct.java index 114abc76..e4bebcd4 100644 --- a/altoslib/AltosUnknownProduct.java +++ b/altoslib/AltosUnknownProduct.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosUnknownProduct extends Exception {  	public String product; diff --git a/altoslib/AltosVersion.java.in b/altoslib/AltosVersion.java.in index a48c532b..c8399f2e 100644 --- a/altoslib/AltosVersion.java.in +++ b/altoslib/AltosVersion.java.in @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosVersion {  	public final static String version = "@VERSION@"; diff --git a/altoslib/AltosVoltage.java b/altoslib/AltosVoltage.java index 8031c805..ef53ac11 100644 --- a/altoslib/AltosVoltage.java +++ b/altoslib/AltosVoltage.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public class AltosVoltage extends AltosUnits { diff --git a/altoslib/AltosWriter.java b/altoslib/AltosWriter.java index 691dc4de..c77e48b0 100644 --- a/altoslib/AltosWriter.java +++ b/altoslib/AltosWriter.java @@ -16,11 +16,11 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  public interface AltosWriter { -	public void write(AltosStateIterable states); +	public void write(AltosFlightSeries series);  	public void close();  } diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 26159421..11b5d562 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -26,6 +26,7 @@ record_files = \  altoslib_JAVA = \  	AltosLib.java \ +	AltosCalData.java \  	AltosCompanion.java \  	AltosConfigData.java \  	AltosConfigDataException.java \ @@ -35,28 +36,34 @@ altoslib_JAVA = \  	AltosCSV.java \  	AltosDebug.java \  	AltosEeprom.java \ +	AltosRecordSet.java \ +	AltosEepromRecord.java \ +	AltosEepromRecordFull.java \ +	AltosEepromRecordTiny.java \ +	AltosEepromRecordMega.java \ +	AltosEepromRecordMetrum.java \ +	AltosEepromRecordMini.java \ +	AltosEepromRecordGps.java \ +	AltosEepromRecordFireTwo.java \ +	AltosEepromRecordSet.java \  	AltosEepromChunk.java \  	AltosEepromDownload.java \ +	AltosEepromMonitor.java \  	AltosEepromFile.java \ -	AltosEepromTM.java \ -	AltosEepromTMini.java \ -	AltosEepromHeader.java \ -	AltosEepromIterable.java \  	AltosEepromList.java \  	AltosEepromLog.java \ -	AltosEepromMega.java \ -	AltosEepromMetrum2.java \ -	AltosEepromMini.java \ -	AltosEepromGPS.java \ -	AltosEepromMonitor.java \ -	AltosEepromFireTwo.java \  	AltosFile.java \  	AltosFlash.java \  	AltosFlashListener.java \ +	AltosDataListener.java \ +	AltosDataProvider.java \ +	AltosFlightSeries.java \  	AltosFlightReader.java \  	AltosFlightStats.java \ +	AltosForce.java \  	AltosFrequency.java \  	AltosGPS.java \ +	AltosGPSTimeValue.java \  	AltosGPSSat.java \  	AltosGreatCircle.java \  	AltosHexfile.java \ @@ -79,9 +86,12 @@ altoslib_JAVA = \  	AltosNoSymbol.java \  	AltosOrient.java \  	AltosParse.java \ +	AltosPressure.java \ +	AltosPresTemp.java \  	AltosPreferences.java \  	AltosPreferencesBackend.java \  	AltosProgrammer.java \ +	AltosPyroName.java \  	AltosReplayReader.java \  	AltosRomconfig.java \  	AltosSavedState.java \ @@ -95,8 +105,8 @@ altoslib_JAVA = \  	AltosSensorMetrum.java \  	AltosSensorTGPS.java \  	AltosState.java \ -	AltosStateIterable.java \ -	AltosStateUpdate.java \ +	AltosStateName.java \ +	AltosStringInputStream.java \  	AltosTelemetry.java \  	AltosTelemetryConfiguration.java \  	AltosTelemetryCompanion.java \ @@ -116,6 +126,9 @@ altoslib_JAVA = \  	AltosTelemetrySensor.java \  	AltosTelemetrySatellite.java \  	AltosTelemetryStandard.java \ +	AltosTime.java \ +	AltosTimeSeries.java \ +	AltosTimeValue.java \  	AltosUnitsListener.java \  	AltosUnknownProduct.java \  	AltosMs5607.java \ @@ -132,6 +145,7 @@ altoslib_JAVA = \  	AltosLocation.java \  	AltosLatitude.java \  	AltosLongitude.java \ +	AltosRotationRate.java \  	AltosPyro.java \  	AltosWriter.java \  	AltosQuaternion.java \ diff --git a/altosui/Altos.java b/altosui/Altos.java index c2cf4090..9f176c4b 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -21,8 +21,8 @@ package altosui;  import java.awt.*;  import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class Altos extends AltosUILib { diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index a4f475cb..ab052e5f 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -22,8 +22,8 @@ import java.util.*;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosAscent extends AltosUIFlightTab {  	JLabel	cur, max; diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java index 52815d6f..95e1d2d9 100644 --- a/altosui/AltosCompanionInfo.java +++ b/altosui/AltosCompanionInfo.java @@ -20,8 +20,8 @@ package altosui;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {  	private AltosFlightInfoTableModel model; diff --git a/altosui/AltosConfig.java b/altosui/AltosConfigFC.java index 07802247..beff71b7 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfigFC.java @@ -23,10 +23,10 @@ import javax.swing.*;  import java.io.*;  import java.util.concurrent.*;  import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; -public class AltosConfig implements ActionListener { +public class AltosConfigFC implements ActionListener {  	class int_ref {  		int	value; @@ -62,7 +62,7 @@ public class AltosConfig implements ActionListener {  	boolean		remote;  	AltosConfigData	data; -	AltosConfigUI	config_ui; +	AltosConfigFCUI	config_ui;  	boolean		serial_started;  	boolean		made_visible; @@ -96,7 +96,7 @@ public class AltosConfig implements ActionListener {  	final static int	serial_mode_reboot = 2;  	class SerialData implements Runnable { -		AltosConfig	config; +		AltosConfigFC	config;  		int		serial_mode;  		void callback(String in_cmd) { @@ -182,7 +182,7 @@ public class AltosConfig implements ActionListener {  			}  		} -		public SerialData(AltosConfig in_config, int in_serial_mode) { +		public SerialData(AltosConfigFC in_config, int in_serial_mode) {  			config = in_config;  			serial_mode = in_serial_mode;  		} @@ -195,7 +195,7 @@ public class AltosConfig implements ActionListener {  	}  	void init_ui () throws InterruptedException, TimeoutException { -		config_ui = new AltosConfigUI(owner, remote); +		config_ui = new AltosConfigFCUI(owner, remote);  		config_ui.addActionListener(this);  		serial_line.set_frame(owner);  		set_ui(); @@ -275,7 +275,7 @@ public class AltosConfig implements ActionListener {  		}  	} -	public AltosConfig(JFrame given_owner) { +	public AltosConfigFC(JFrame given_owner) {  		owner = given_owner;  		device = AltosDeviceUIDialog.show(owner, Altos.product_any); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigFCUI.java index e5f1949a..c0c37254 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigFCUI.java @@ -23,10 +23,10 @@ import java.awt.event.*;  import javax.swing.*;  import javax.swing.event.*;  import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; -public class AltosConfigUI +public class AltosConfigFCUI  	extends AltosUIDialog  	implements ActionListener, ItemListener, DocumentListener, AltosConfigValues, AltosUnitsListener  { @@ -159,9 +159,9 @@ public class AltosConfigUI  	/* A window listener to catch closing events and tell the config code */  	class ConfigListener extends WindowAdapter { -		AltosConfigUI	ui; +		AltosConfigFCUI	ui; -		public ConfigListener(AltosConfigUI this_ui) { +		public ConfigListener(AltosConfigFCUI this_ui) {  			ui = this_ui;  		} @@ -193,46 +193,46 @@ public class AltosConfigUI  	}  	void set_radio_enable_tool_tip() { -		if (radio_enable_value.isEnabled()) +		if (radio_enable_value.isVisible())  			radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");  		else  			radio_enable_value.setToolTipText("Firmware version does not support disabling radio");  	}  	void set_rate_tool_tip() { -		if (rate_value.isEnabled()) +		if (rate_value.isVisible())  			rate_value.setToolTipText("Select telemetry baud rate");  		else  			rate_value.setToolTipText("Firmware version does not support variable telemetry rates");  	}  	void set_aprs_interval_tool_tip() { -		if (aprs_interval_value.isEnabled()) +		if (aprs_interval_value.isVisible())  			aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports");  		else  			aprs_interval_value.setToolTipText("Hardware doesn't support APRS");  	}  	void set_aprs_ssid_tool_tip() { -		if (aprs_ssid_value.isEnabled()) +		if (aprs_ssid_value.isVisible())  			aprs_ssid_value.setToolTipText("Set the APRS SSID (secondary station identifier)"); -		else if (aprs_ssid_value.isEnabled()) +		else if (aprs_ssid_value.isVisible())  			aprs_ssid_value.setToolTipText("Software version doesn't support setting the APRS SSID");  		else  			aprs_ssid_value.setToolTipText("Hardware doesn't support APRS");  	}  	void set_aprs_format_tool_tip() { -		if (aprs_format_value.isEnabled()) +		if (aprs_format_value.isVisible())  			aprs_format_value.setToolTipText("Set the APRS format (compressed/uncompressed)"); -		else if (aprs_format_value.isEnabled()) +		else if (aprs_format_value.isVisible())  			aprs_format_value.setToolTipText("Software version doesn't support setting the APRS format");  		else  			aprs_format_value.setToolTipText("Hardware doesn't support APRS");  	}  	void set_flight_log_max_tool_tip() { -		if (flight_log_max_value.isEnabled()) +		if (flight_log_max_value.isVisible())  			flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");  		else {  			if (is_telemini_v1()) @@ -243,14 +243,14 @@ public class AltosConfigUI  	}  	void set_ignite_mode_tool_tip() { -		if (ignite_mode_value.isEnabled()) +		if (ignite_mode_value.isVisible())  			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()) +		if (pad_orientation_value.isVisible())  			pad_orientation_value.setToolTipText("How will the computer be mounted in the airframe");  		else {  			if (is_telemetrum()) @@ -263,14 +263,14 @@ public class AltosConfigUI  	}  	void set_beep_tool_tip() { -		if (beep_value.isEnabled()) +		if (beep_value.isVisible())  			beep_value.setToolTipText("What frequency the beeper will sound at");  		else  			beep_value.setToolTipText("Older firmware could not select beeper frequency");  	}  	/* Build the UI using a grid bag */ -	public AltosConfigUI(JFrame in_owner, boolean remote) { +	public AltosConfigFCUI(JFrame in_owner, boolean remote) {  		super (in_owner, "Configure Flight Computer", false);  		owner = in_owner; @@ -959,12 +959,10 @@ public class AltosConfigUI  	}  	public void set_main_deploy(int new_main_deploy) { -		main_deploy_value.setSelectedItem(AltosConvert.height.say(new_main_deploy)); -		main_deploy_value.setEnabled(new_main_deploy >= 0); - -		main_deploy_value.setVisible(new_main_deploy >= 0); -		main_deploy_label.setVisible(new_main_deploy >= 0); - +		if (new_main_deploy != AltosLib.MISSING) +			main_deploy_value.setSelectedItem(AltosConvert.height.say(new_main_deploy)); +		main_deploy_value.setVisible(new_main_deploy != AltosLib.MISSING); +		main_deploy_label.setVisible(new_main_deploy != AltosLib.MISSING);  	}  	public int main_deploy() throws AltosConfigDataException { @@ -1008,7 +1006,7 @@ public class AltosConfigUI  		} catch (ParseException pe) {  		} -		if (tracker_motion_value.isEnabled()) { +		if (tracker_motion_value.isVisible()) {  			String motion = tracker_motion_value.getSelectedItem().toString();  			tracker_motion_label.setText(get_tracker_motion_label());  			set_tracker_motion_values(); @@ -1024,11 +1022,10 @@ public class AltosConfigUI  	}  	public void set_apogee_delay(int new_apogee_delay) { -		apogee_delay_value.setVisible(new_apogee_delay >= 0); -		apogee_delay_label.setVisible(new_apogee_delay >= 0); - -		apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay)); -		apogee_delay_value.setEnabled(new_apogee_delay >= 0); +		if (new_apogee_delay != AltosLib.MISSING) +			apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay)); +		apogee_delay_value.setVisible(new_apogee_delay != AltosLib.MISSING); +		apogee_delay_label.setVisible(new_apogee_delay != AltosLib.MISSING);  	}  	private int parse_int(String name, String s, boolean split) throws AltosConfigDataException { @@ -1047,11 +1044,11 @@ public class AltosConfigUI  	}  	public void set_apogee_lockout(int new_apogee_lockout) { -		apogee_lockout_value.setSelectedItem(Integer.toString(new_apogee_lockout)); -		apogee_lockout_value.setEnabled(new_apogee_lockout >= 0); +		if (new_apogee_lockout != AltosLib.MISSING) +			apogee_lockout_value.setSelectedItem(Integer.toString(new_apogee_lockout)); -		apogee_lockout_value.setVisible(new_apogee_lockout >= 0); -		apogee_lockout_label.setVisible(new_apogee_lockout >= 0); +		apogee_lockout_value.setVisible(new_apogee_lockout != AltosLib.MISSING); +		apogee_lockout_label.setVisible(new_apogee_lockout != AltosLib.MISSING);  	}  	public int apogee_lockout() throws AltosConfigDataException { @@ -1059,8 +1056,10 @@ public class AltosConfigUI  	}  	public void set_radio_frequency(double new_radio_frequency) { -		radio_frequency_label.setVisible(new_radio_frequency >= 0); -		radio_frequency_value.set_frequency(new_radio_frequency); +		if (new_radio_frequency != AltosLib.MISSING) +			radio_frequency_value.set_frequency(new_radio_frequency); +		radio_frequency_label.setVisible(new_radio_frequency != AltosLib.MISSING); +		radio_frequency_value.setVisible(new_radio_frequency != AltosLib.MISSING);  	}  	public double radio_frequency() { @@ -1068,40 +1067,33 @@ public class AltosConfigUI  	}  	public void set_radio_calibration(int new_radio_calibration) { -		radio_calibration_value.setVisible(new_radio_calibration >= 0); -		radio_calibration_label.setVisible(new_radio_calibration >= 0); - -		if (new_radio_calibration < 0) -			radio_calibration_value.setText("Disabled"); -		else +		if (new_radio_calibration != AltosLib.MISSING)  			radio_calibration_value.setText(String.format("%d", new_radio_calibration)); +		radio_calibration_value.setVisible(new_radio_calibration != AltosLib.MISSING); +		radio_calibration_label.setVisible(new_radio_calibration != AltosLib.MISSING);  	}  	public void set_radio_enable(int new_radio_enable) { -		radio_enable_label.setVisible(new_radio_enable >= 0); -		radio_enable_value.setVisible(new_radio_enable >= 0); - -		if (new_radio_enable >= 0) { -			radio_enable_value.setSelected(new_radio_enable > 0); -			radio_enable_value.setEnabled(true); -		} else { -			radio_enable_value.setSelected(true); -			radio_enable_value.setEnabled(false); -		} +		if (new_radio_enable != AltosLib.MISSING) +			radio_enable_value.setSelected(new_radio_enable != 0); +		radio_enable_label.setVisible(new_radio_enable != AltosLib.MISSING); +		radio_enable_value.setVisible(new_radio_enable != AltosLib.MISSING);  		set_radio_enable_tool_tip();  	}  	public int radio_enable() { -		if (radio_enable_value.isEnabled()) +		if (radio_enable_value.isVisible())  			return radio_enable_value.isSelected() ? 1 : 0;  		else -			return -1; +			return AltosLib.MISSING;  	}  	public void set_telemetry_rate(int new_rate) { -		rate_label.setVisible(new_rate >= 0); - -		rate_value.set_rate(new_rate); +		if (new_rate != AltosLib.MISSING) +			rate_value.set_rate(new_rate); +		rate_label.setVisible(new_rate != AltosLib.MISSING); +		rate_value.setVisible(new_rate != AltosLib.MISSING); +		set_rate_tool_tip();  	}  	public int telemetry_rate() { @@ -1109,14 +1101,16 @@ public class AltosConfigUI  	}  	public void set_callsign(String new_callsign) { +		if (new_callsign != null) +			callsign_value.setText(new_callsign);  		callsign_value.setVisible(new_callsign != null);  		callsign_label.setVisible(new_callsign != null); - -		callsign_value.setText(new_callsign);  	}  	public String callsign() { -		return callsign_value.getText(); +		if (callsign_value.isVisible()) +			return callsign_value.getText(); +		return null;  	}  	int	flight_log_max_limit; @@ -1133,11 +1127,12 @@ public class AltosConfigUI  	}  	public void set_flight_log_max(int new_flight_log_max) { -		flight_log_max_value.setVisible(new_flight_log_max >= 0); -		flight_log_max_label.setVisible(new_flight_log_max >= 0); - -		flight_log_max_value.setSelectedItem(flight_log_max_label(new_flight_log_max)); -		flight_log_max = new_flight_log_max; +		if (new_flight_log_max != AltosLib.MISSING) { +			flight_log_max_value.setSelectedItem(flight_log_max_label(new_flight_log_max)); +			flight_log_max = new_flight_log_max; +		} +		flight_log_max_value.setVisible(new_flight_log_max != AltosLib.MISSING); +		flight_log_max_label.setVisible(new_flight_log_max != AltosLib.MISSING);  		set_flight_log_max_tool_tip();  	} @@ -1147,84 +1142,92 @@ public class AltosConfigUI  	}  	public int flight_log_max() throws AltosConfigDataException { -		return parse_int("flight log max", flight_log_max_value.getSelectedItem().toString(), true); +		if (flight_log_max_value.isVisible()) +			return parse_int("flight log max", flight_log_max_value.getSelectedItem().toString(), true); +		return AltosLib.MISSING;  	}  	public void set_flight_log_max_limit(int new_flight_log_max_limit) {  		flight_log_max_limit = new_flight_log_max_limit; -		flight_log_max_value.removeAllItems(); -		for (int i = 8; i >= 1; i--) { -			int	size = flight_log_max_limit / i; -			flight_log_max_value.addItem(String.format("%d (%d flights)", size, i)); +		if (new_flight_log_max_limit != AltosLib.MISSING) { +			flight_log_max_value.removeAllItems(); +			for (int i = 8; i >= 1; i--) { +				int	size = flight_log_max_limit / i; +				flight_log_max_value.addItem(String.format("%d (%d flights)", size, i)); +			}  		}  		if (flight_log_max != 0)  			set_flight_log_max(flight_log_max);  	}  	public void set_ignite_mode(int new_ignite_mode) { -		ignite_mode_value.setVisible(new_ignite_mode >= 0); -		ignite_mode_label.setVisible(new_ignite_mode >= 0); - -		if (new_ignite_mode >= ignite_mode_values.length) -			new_ignite_mode = 0; -		if (new_ignite_mode < 0) { -			ignite_mode_value.setEnabled(false); -			new_ignite_mode = 0; -		} else { -			ignite_mode_value.setEnabled(true); +		if (new_ignite_mode != AltosLib.MISSING) { +			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; +			} else { +				ignite_mode_value.setEnabled(true); +			} +			ignite_mode_value.setSelectedIndex(new_ignite_mode);  		} -		ignite_mode_value.setSelectedIndex(new_ignite_mode); +		ignite_mode_value.setVisible(new_ignite_mode != AltosLib.MISSING); +		ignite_mode_label.setVisible(new_ignite_mode != AltosLib.MISSING); +  		set_ignite_mode_tool_tip();  	}  	public int ignite_mode() { -		if (ignite_mode_value.isEnabled()) +		if (ignite_mode_value.isVisible())  			return ignite_mode_value.getSelectedIndex();  		else -			return -1; +			return AltosLib.MISSING;  	}  	public void set_pad_orientation(int new_pad_orientation) { -		pad_orientation_value.setVisible(new_pad_orientation >= 0); -		pad_orientation_label.setVisible(new_pad_orientation >= 0); - -		if (new_pad_orientation >= pad_orientation_values.length) -			new_pad_orientation = 0; -		if (new_pad_orientation < 0) -			new_pad_orientation = 0; -		pad_orientation_value.setSelectedIndex(new_pad_orientation); +		if (new_pad_orientation != AltosLib.MISSING) { +			if (new_pad_orientation >= pad_orientation_values.length) +				new_pad_orientation = 0; +			if (new_pad_orientation < 0) +				new_pad_orientation = 0; +			pad_orientation_value.setSelectedIndex(new_pad_orientation); +		} +		pad_orientation_value.setVisible(new_pad_orientation != AltosLib.MISSING); +		pad_orientation_label.setVisible(new_pad_orientation != AltosLib.MISSING); +  		set_pad_orientation_tool_tip();  	}  	public int pad_orientation() { -		if (pad_orientation_value.isEnabled()) +		if (pad_orientation_value.isVisible())  			return pad_orientation_value.getSelectedIndex();  		else -			return -1; +			return AltosLib.MISSING;  	}  	public void set_beep(int new_beep) { -		beep_value.setVisible(new_beep >= 0); -		beep_label.setVisible(new_beep >= 0); - -		int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5); -		for (int i = 0; i < beep_values.length; i++) -			if (new_beep == AltosConvert.beep_freq_to_value(Integer.parseInt(beep_values[i]))) { -				beep_value.setSelectedIndex(i); -				set_beep_tool_tip(); -				return; -			} -		beep_value.setSelectedItem(String.format("%d", new_freq)); -		beep_value.setEnabled(new_beep >= 0); +		if (new_beep != AltosLib.MISSING) { +			int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5); +			for (int i = 0; i < beep_values.length; i++) +				if (new_beep == AltosConvert.beep_freq_to_value(Integer.parseInt(beep_values[i]))) { +					beep_value.setSelectedIndex(i); +					set_beep_tool_tip(); +					return; +				} +			beep_value.setSelectedItem(String.format("%d", new_freq)); +		} +		beep_value.setVisible(new_beep != AltosLib.MISSING); +		beep_label.setVisible(new_beep != AltosLib.MISSING);  		set_beep_tool_tip();  	}  	public int beep() { -		if (beep_value.isEnabled()) +		if (beep_value.isVisible())  			return AltosConvert.beep_freq_to_value(Integer.parseInt(beep_value.getSelectedItem().toString()));  		else -			return -1; +			return AltosLib.MISSING;  	}  	String[] tracker_motion_values() { @@ -1248,58 +1251,53 @@ public class AltosConfigUI  	}  	void set_tracker_tool_tip() { -		if (tracker_motion_value.isEnabled()) +		if (tracker_motion_value.isVisible())  			tracker_motion_value.setToolTipText("How far the device must move before logging");  		else  			tracker_motion_value.setToolTipText("This device doesn't disable logging when stationary"); -		if (tracker_interval_value.isEnabled()) +		if (tracker_interval_value.isVisible())  			tracker_interval_value.setToolTipText("How often to report GPS position");  		else  			tracker_interval_value.setToolTipText("This device can't configure interval");  	}  	public void set_tracker_motion(int tracker_motion) { -		tracker_motion_label.setVisible(tracker_motion >= 0); -		tracker_motion_value.setVisible(tracker_motion >= 0); - -		if (tracker_motion < 0) { -			tracker_motion_value.setEnabled(false); -		} else { -			tracker_motion_value.setEnabled(true); +		if (tracker_motion != AltosLib.MISSING)  			tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion)); -		} +		tracker_motion_label.setVisible(tracker_motion != AltosLib.MISSING); +		tracker_motion_value.setVisible(tracker_motion != AltosLib.MISSING);  	}  	public int tracker_motion() throws AltosConfigDataException { -		String str = tracker_motion_value.getSelectedItem().toString(); -		try { -			return (int) (AltosConvert.height.parse_locale(str) + 0.5); -		} catch (ParseException pe) { -			throw new AltosConfigDataException("invalid tracker motion %s", str); +		if (tracker_motion_value.isVisible()) { +			String str = tracker_motion_value.getSelectedItem().toString(); +			try { +				return (int) (AltosConvert.height.parse_locale(str) + 0.5); +			} catch (ParseException pe) { +				throw new AltosConfigDataException("invalid tracker motion %s", str); +			}  		} +		return AltosLib.MISSING;  	}  	public void set_tracker_interval(int tracker_interval) { -		tracker_interval_label.setVisible(tracker_interval >= 0); -		tracker_interval_value.setVisible(tracker_interval >= 0); - -		if (tracker_interval< 0) { -			tracker_interval_value.setEnabled(false); -		} else { -			tracker_interval_value.setEnabled(true); +		if (tracker_interval != AltosLib.MISSING)  			tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval)); -		} +		tracker_interval_label.setVisible(tracker_interval != AltosLib.MISSING); +		tracker_interval_value.setVisible(tracker_interval != AltosLib.MISSING);  	}  	public int tracker_interval() throws AltosConfigDataException { -		return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false); +		if (tracker_interval_value.isVisible()) +			return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false); +		return AltosLib.MISSING;  	}  	public void set_pyros(AltosPyro[] new_pyros) {  		pyros = new_pyros; -		pyro.setVisible(pyros != null);  		if (pyros != null && pyro_ui != null)  			pyro_ui.set_pyros(pyros); +		pyro.setVisible(pyros != null);  	}  	public AltosPyro[] pyros() throws AltosConfigDataException { @@ -1310,9 +1308,9 @@ public class AltosConfigUI  	public void set_pyro_firing_time(double new_pyro_firing_time) {  		pyro_firing_time = new_pyro_firing_time; -		pyro.setVisible(pyro_firing_time >= 0); -		if (pyro_firing_time >= 0 && pyro_ui != null) +		if (pyro_firing_time != AltosLib.MISSING && pyro_ui != null)  			pyro_ui.set_pyro_firing_time(pyro_firing_time); +		pyro.setVisible(pyro_firing_time != AltosLib.MISSING);  	}  	public double pyro_firing_time() throws AltosConfigDataException { @@ -1322,49 +1320,49 @@ public class AltosConfigUI  	}  	public void set_aprs_interval(int new_aprs_interval) { -		aprs_interval_value.setVisible(new_aprs_interval >= 0); -		aprs_interval_label.setVisible(new_aprs_interval >= 0); - -		String	s; - -		if (new_aprs_interval <= 0) -			s = "Disabled"; -		else -			s = Integer.toString(new_aprs_interval); -		aprs_interval_value.setSelectedItem(s); +		if (new_aprs_interval != AltosLib.MISSING) +			aprs_interval_value.setSelectedItem(Integer.toString(new_aprs_interval)); +		aprs_interval_value.setVisible(new_aprs_interval != AltosLib.MISSING); +		aprs_interval_label.setVisible(new_aprs_interval != AltosLib.MISSING);  		set_aprs_interval_tool_tip();  	}  	public int aprs_interval() throws AltosConfigDataException { -		String	s = aprs_interval_value.getSelectedItem().toString(); +		if (aprs_interval_value.isVisible()) { +			String	s = aprs_interval_value.getSelectedItem().toString(); -		if (s.equals("Disabled")) -			return 0; -		return parse_int("aprs interval", s, false); +			return parse_int("aprs interval", s, false); +		} +		return AltosLib.MISSING;  	}  	public void set_aprs_ssid(int new_aprs_ssid) { -		aprs_ssid_value.setVisible(new_aprs_ssid >= 0); -		aprs_ssid_label.setVisible(new_aprs_ssid >= 0); - -		aprs_ssid_value.setSelectedItem(Math.max(0,new_aprs_ssid)); +		if (new_aprs_ssid != AltosLib.MISSING) +			aprs_ssid_value.setSelectedItem(new_aprs_ssid); +		aprs_ssid_value.setVisible(new_aprs_ssid != AltosLib.MISSING); +		aprs_ssid_label.setVisible(new_aprs_ssid != AltosLib.MISSING);  		set_aprs_ssid_tool_tip();  	}  	public int aprs_ssid() throws AltosConfigDataException { -		Integer i = (Integer) aprs_ssid_value.getSelectedItem(); -		return i; +		if (aprs_ssid_value.isVisible()) { +			Integer i = (Integer) aprs_ssid_value.getSelectedItem(); +			return i; +		} +		return AltosLib.MISSING;  	}  	public void set_aprs_format(int new_aprs_format) { -		aprs_format_value.setVisible(new_aprs_format >= 0); -		aprs_format_label.setVisible(new_aprs_format >= 0); - -		aprs_format_value.setSelectedIndex(Math.max(0,new_aprs_format)); +		if (new_aprs_format != AltosLib.MISSING) +			aprs_format_value.setSelectedIndex(new_aprs_format); +		aprs_format_value.setVisible(new_aprs_format != AltosLib.MISSING); +		aprs_format_label.setVisible(new_aprs_format != AltosLib.MISSING);  		set_aprs_format_tool_tip();  	}  	public int aprs_format() throws AltosConfigDataException { -		return aprs_format_value.getSelectedIndex(); +		if (aprs_format_value.isVisible()) +			return aprs_format_value.getSelectedIndex(); +		return AltosLib.MISSING;  	}  } diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java index 2d4b216c..cd887c00 100644 --- a/altosui/AltosConfigPyroUI.java +++ b/altosui/AltosConfigPyroUI.java @@ -23,14 +23,14 @@ import java.awt.*;  import java.awt.event.*;  import javax.swing.*;  import javax.swing.event.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosConfigPyroUI  	extends AltosUIDialog  	implements ItemListener, DocumentListener, AltosUnitsListener, ActionListener  { -	AltosConfigUI	owner; +	AltosConfigFCUI	owner;  	Container	pane;  	static Insets il = new Insets(4,4,4,4); @@ -347,9 +347,9 @@ public class AltosConfigPyroUI  	/* A window listener to catch closing events and tell the config code */  	class ConfigListener extends WindowAdapter {  		AltosConfigPyroUI	ui; -		AltosConfigUI		owner; +		AltosConfigFCUI		owner; -		public ConfigListener(AltosConfigPyroUI this_ui, AltosConfigUI this_owner) { +		public ConfigListener(AltosConfigPyroUI this_ui, AltosConfigFCUI this_owner) {  			ui = this_ui;  			owner = this_owner;  		} @@ -367,7 +367,7 @@ public class AltosConfigPyroUI  			setVisible(false);  	} -	public AltosConfigPyroUI(AltosConfigUI in_owner, AltosPyro[] pyros, double pyro_firing_time) { +	public AltosConfigPyroUI(AltosConfigFCUI in_owner, AltosPyro[] pyros, double pyro_firing_time) {  		super(in_owner, "Configure Pyro Channels", false); diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java index 621db3c0..9fedc56d 100644 --- a/altosui/AltosConfigTD.java +++ b/altosui/AltosConfigTD.java @@ -22,8 +22,8 @@ import java.awt.event.*;  import javax.swing.*;  import java.io.*;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosConfigTD implements ActionListener { diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java index 529c2fa2..3ff56218 100644 --- a/altosui/AltosConfigTDUI.java +++ b/altosui/AltosConfigTDUI.java @@ -22,8 +22,8 @@ import java.awt.*;  import java.awt.event.*;  import javax.swing.*;  import javax.swing.event.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosConfigTDUI  	extends AltosUIDialog diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 6aefb3a6..acafc659 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -23,7 +23,7 @@ import java.awt.event.*;  import java.beans.*;  import javax.swing.*;  import javax.swing.event.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosConfigureUI  	extends AltosUIConfigure diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 0c3a8e9e..2cc65b08 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -22,8 +22,8 @@ import java.util.*;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosDescent extends AltosUIFlightTab { diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index 4288fc9f..a5e5a4ef 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -20,8 +20,8 @@ package altosui;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {  	GridBagLayout	layout; @@ -93,14 +93,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay  		}  		void show(AltosState state, AltosListenerState listener_state) { -			if (!same_call(state.callsign)) { +			if (!same_call(state.cal_data().callsign)) {  				show(); -				value.setText(state.callsign); -				if (state.callsign == null) +				value.setText(state.cal_data().callsign); +				if (state.cal_data().callsign == null)  					setVisible(false);  				else  					setVisible(true); -				last_call = state.callsign; +				last_call = state.cal_data().callsign;  			}  		} @@ -120,13 +120,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay  		int	last_serial = -1;  		void show(AltosState state, AltosListenerState listener_state) { -			if (state.serial != last_serial) { +			AltosCalData	cal_data = state.cal_data(); +			if (cal_data.serial != last_serial) {  				show(); -				if (state.serial == AltosLib.MISSING) +				if (cal_data.serial == AltosLib.MISSING)  					value.setText("none");  				else -					value.setText(String.format("%d", state.serial)); -				last_serial = state.serial; +					value.setText(String.format("%d", cal_data.serial)); +				last_serial = cal_data.serial;  			}  		} @@ -147,13 +148,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay  		int	last_flight = -1;  		void show(AltosState state, AltosListenerState listener_state) { -			if (state.flight != last_flight) { +			AltosCalData cal_data = state.cal_data(); +			if (cal_data.flight != last_flight) {  				show(); -				if (state.flight == AltosLib.MISSING) +				if (cal_data.flight == AltosLib.MISSING)  					value.setText("none");  				else -					value.setText(String.format("%d", state.flight)); -				last_flight = state.flight; +					value.setText(String.format("%d", cal_data.flight)); +				last_flight = cal_data.flight;  			}  		} diff --git a/altosui/AltosFlightStatusTableModel.java b/altosui/AltosFlightStatusTableModel.java index 7b872df9..9c4e1bee 100644 --- a/altosui/AltosFlightStatusTableModel.java +++ b/altosui/AltosFlightStatusTableModel.java @@ -28,7 +28,7 @@ import java.util.*;  import java.text.*;  import java.util.prefs.*;  import java.util.concurrent.LinkedBlockingQueue; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosFlightStatusTableModel extends AbstractTableModel {  	private String[] columnNames = { diff --git a/altosui/AltosFlightStatusUpdate.java b/altosui/AltosFlightStatusUpdate.java index 82ef43c2..b8b0d38a 100644 --- a/altosui/AltosFlightStatusUpdate.java +++ b/altosui/AltosFlightStatusUpdate.java @@ -19,7 +19,7 @@  package altosui;  import java.awt.event.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosFlightStatusUpdate implements ActionListener { diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index cf03d2dc..44e995be 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -23,8 +23,8 @@ import java.awt.event.*;  import javax.swing.*;  import java.util.*;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {  	AltosVoice		voice; @@ -36,7 +36,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {  	JTabbedPane	pane;  	AltosPad	pad; -	AltosIgnitor	ignitor; +	AltosIgnitor	igniter;  	AltosAscent	ascent;  	AltosDescent	descent;  	AltosLanded	landed; @@ -45,7 +45,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {  	boolean		has_map;  	boolean		has_companion;  	boolean		has_state; -	boolean		has_ignitor; +	boolean		has_igniter;  	private AltosFlightStatus flightStatus;  	private AltosInfoTable flightInfo; @@ -101,7 +101,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {  		status_update.saved_listener_state = listener_state;  		if (state == null) -			state = new AltosState(); +			state = new AltosState(new AltosCalData());  		if (state.state() != Altos.ao_flight_startup) {  			if (!has_state) { @@ -115,21 +115,20 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {  		JComponent tab = which_tab(state);  		if (tab != cur_tab) { -			if (cur_tab == pane.getSelectedComponent()) { +			if (cur_tab == pane.getSelectedComponent())  				pane.setSelectedComponent(tab); -			}  			cur_tab = tab;  		} -		if (ignitor.should_show(state)) { -			if (!has_ignitor) { -				pane.add("Ignitor", ignitor); -				has_ignitor = true; +		if (igniter.should_show(state)) { +			if (!has_igniter) { +				pane.add("Ignitor", igniter); +				has_igniter = true;  			}  		} else { -			if (has_ignitor) { -				pane.remove(ignitor); -				has_ignitor = false; +			if (has_igniter) { +				pane.remove(igniter); +				has_igniter = false;  			}  		} @@ -145,7 +144,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {  			}  		} -		if (state.gps != null && state.gps.connected) { +		if (state.gps != null) {  			if (!has_map) {  				pane.add("Site Map", sitemap);  				has_map = true; @@ -272,8 +271,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {  		displays.add(pad);  		pane.add("Status", pad); -		ignitor = new AltosIgnitor(); -		displays.add(ignitor); +		igniter = new AltosIgnitor(); +		displays.add(igniter);  		ascent = new AltosAscent();  		displays.add(ascent);  		descent = new AltosDescent(); diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 4ca2b77c..f6c906c6 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -24,8 +24,8 @@ import java.util.ArrayList;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  import org.jfree.chart.ChartPanel;  import org.jfree.chart.JFreeChart; @@ -37,22 +37,35 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt  	AltosGraph		graph;  	AltosUIEnable		enable;  	AltosUIMap		map; -	AltosState		state; -	AltosGraphDataSet	graphDataSet;  	AltosFlightStats	stats;  	AltosFlightStatsTable	statsTable; +	AltosGPS		gps;  	boolean			has_gps; -	void fill_map(AltosStateIterable states) { -		boolean		any_gps = false; -		for (AltosState state : states) { -			if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { -				if (map == null) -					map = new AltosUIMap(); -				map.show(state, null); -				has_gps = true; +	void fill_map(AltosFlightSeries flight_series) { +		boolean			any_gps = false; +		AltosGPSTimeValue	gtv_last = null; + +		if (flight_series.gps_series != null) { +			for (AltosGPSTimeValue gtv : flight_series.gps_series) { +				gtv_last = gtv; +				AltosGPS gps = gtv.gps; +				if (gps != null && +				    gps.locked && +				    gps.nsat >= 4) { +					if (map == null) +						map = new AltosUIMap(); +					map.show(gps, (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time)); +					this.gps = gps; +					has_gps = true; +				}  			}  		} +		if (gtv_last != null) { +			int state = (int) flight_series.value_after(AltosFlightSeries.state_name, gtv_last.time); +			if (state == AltosLib.ao_flight_landed) +				map.show(gtv_last.gps, state); +		}  	}  	public void font_size_changed(int font_size) { @@ -69,18 +82,24 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt  			enable.units_changed(imperial_units);  	} -	AltosGraphUI(AltosStateIterable states, File file) throws InterruptedException, IOException { +	AltosGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException {  		super(file.getName()); -		state = null; +		AltosCalData	cal_data = set.cal_data(); +  		pane = new JTabbedPane();  		enable = new AltosUIEnable(); -		stats = new AltosFlightStats(states); -		graphDataSet = new AltosGraphDataSet(states); +		AltosUIFlightSeries flight_series = new AltosUIFlightSeries(cal_data); + +		set.capture_series(flight_series); + +		flight_series.finish(); + +		stats = new AltosFlightStats(flight_series); -		graph = new AltosGraph(enable, stats, graphDataSet); +		graph = new AltosGraph(enable, stats, flight_series);  		statsTable = new AltosFlightStatsTable(stats); @@ -89,7 +108,7 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt  		pane.add("Flight Statistics", statsTable);  		has_gps = false; -		fill_map(states); +		fill_map(flight_series);  		if (has_gps)  			pane.add("Map", map); @@ -108,7 +127,7 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt  		pack();  		setVisible(true); -		if (state != null && has_gps) -			map.centre(state); +		if (gps != null) +			map.centre(gps);  	}  } diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 4d5c3b2d..a2696f15 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -25,8 +25,8 @@ import javax.swing.event.*;  import java.io.*;  import java.util.concurrent.*;  import java.util.Arrays; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {  	AltosDevice		device; @@ -34,12 +34,12 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl  	AltosPad		pad;  	AltosInfoTable		flightInfo;  	AltosFlightStatus	flightStatus; -	AltosIgnitor		ignitor; +	AltosIgnitor		igniter;  	AltosIdleMonitor	thread;  	AltosUIMap      	sitemap;  	int			serial;  	boolean			remote; -	boolean			has_ignitor; +	boolean			has_igniter;  	boolean			has_map;  	void stop_display() { @@ -75,15 +75,15 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl  	public void show(AltosState state, AltosListenerState listener_state) {  		status_update.saved_state = state; -		if (ignitor.should_show(state)) { -			if (!has_ignitor) { -				pane.add("Ignitor", ignitor); -				has_ignitor = true; +		if (igniter.should_show(state)) { +			if (!has_igniter) { +				pane.add("Ignitor", igniter); +				has_igniter = true;  			}  		} else { -			if (has_ignitor) { -				pane.remove(ignitor); -				has_ignitor = false; +			if (has_igniter) { +				pane.remove(igniter); +				has_igniter = false;  			}  		}  		if (state.gps != null && state.gps.connected) { @@ -102,8 +102,8 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl  			pad.show(state, listener_state);  			flightStatus.show(state, listener_state);  			flightInfo.show(state, listener_state); -			if (has_ignitor) -				ignitor.show(state, listener_state); +			if (has_igniter) +				igniter.show(state, listener_state);  			if (has_map)  				sitemap.show(state, listener_state);  //		} catch (Exception e) { @@ -274,7 +274,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl  		flightInfo = new AltosInfoTable();  		pane.add("Table", new JScrollPane(flightInfo)); -		ignitor = new AltosIgnitor(); +		igniter = new AltosIgnitor();  		sitemap = new AltosUIMap(); diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 15493b8a..debbf763 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -25,8 +25,8 @@ import java.io.*;  import java.text.*;  import java.util.*;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosIgniteUI  	extends AltosUIDialog @@ -213,6 +213,8 @@ public class AltosIgniteUI  			fired();  		} else if (reply.startsWith("npyro")) {  			npyro = Integer.parseInt(reply.substring(6)); +			if (npyro == AltosLib.MISSING) +				npyro = 0;  			make_ui();  		}  	} @@ -255,15 +257,11 @@ public class AltosIgniteUI  	boolean	getting_status = false; -	boolean	visible = false; -  	void set_ignite_status() {  		getting_status = false;  		poll_remaining = 2; -		if (!visible) { -			visible = true; +		if (!isVisible())  			setVisible(true); -		}  	}  	void poll_ignite_status() { diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java index fabf4320..7c7d1fba 100644 --- a/altosui/AltosIgnitor.java +++ b/altosui/AltosIgnitor.java @@ -21,65 +21,65 @@ package altosui;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosIgnitor extends AltosUIFlightTab {  	public class Ignitor extends AltosUIUnitsIndicator { -		int		ignitor; +		int		igniter;  		public double value(AltosState state, int i) { -			if (state.ignitor_voltage == null || -			    state.ignitor_voltage.length < ignitor) +			if (state.igniter_voltage == null || +			    state.igniter_voltage.length < igniter)  				return AltosLib.MISSING; -			return state.ignitor_voltage[ignitor]; +			return state.igniter_voltage[igniter];  		}  		public double good() { return AltosLib.ao_igniter_good; }  		public Ignitor (AltosUIFlightTab container, int y) { -			super(container, y, AltosConvert.voltage, String.format ("%s Voltage", AltosLib.ignitor_name(y)), 1, true, 1); -			ignitor = y; +			super(container, y, AltosConvert.voltage, String.format ("%s Voltage", AltosLib.igniter_name(y)), 1, true, 1); +			igniter = y;  		}  	} -	Ignitor[] ignitors; +	Ignitor[] igniters;  	public void show(AltosState state, AltosListenerState listener_state) {  		if (isShowing()) -			make_ignitors(state); +			make_igniters(state);  		super.show(state, listener_state);  	}  	public boolean should_show(AltosState state) {  		if (state == null)  			return false; -		if (state.ignitor_voltage == null) +		if (state.igniter_voltage == null)  			return false; -		return state.ignitor_voltage.length > 0; +		return state.igniter_voltage.length > 0;  	} -	void make_ignitors(AltosState state) { -		int n = (state == null || state.ignitor_voltage == null) ? 0 : state.ignitor_voltage.length; -		int old_n = ignitors == null ? 0 : ignitors.length; +	void make_igniters(AltosState state) { +		int n = (state == null || state.igniter_voltage == null) ? 0 : state.igniter_voltage.length; +		int old_n = igniters == null ? 0 : igniters.length;  		if (n != old_n) { -			if (ignitors != null) { -				for (int i = 0; i < ignitors.length; i++) { -					remove(ignitors[i]); -					ignitors[i].remove(this); -					ignitors = null; +			if (igniters != null) { +				for (int i = 0; i < igniters.length; i++) { +					remove(igniters[i]); +					igniters[i].remove(this); +					igniters = null;  				}  			}  			if (n > 0) {  				setVisible(true); -				ignitors = new Ignitor[n]; +				igniters = new Ignitor[n];  				for (int i = 0; i < n; i++) { -					ignitors[i] = new Ignitor(this, i); -					add(ignitors[i]); +					igniters[i] = new Ignitor(this, i); +					add(igniters[i]);  				}  			} else  				setVisible(false); diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index ded08537..c2e14923 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -22,8 +22,8 @@ import java.awt.*;  import java.awt.event.*;  import javax.swing.*;  import java.io.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosLanded extends AltosUIFlightTab implements ActionListener { @@ -123,18 +123,17 @@ public class AltosLanded extends AltosUIFlightTab implements ActionListener {  			if (file != null) {  				String	filename = file.getName();  				try { -					AltosStateIterable states = null; +					AltosRecordSet record_set = null; +					FileInputStream in = new FileInputStream(file);  					if (filename.endsWith("eeprom")) { -						FileInputStream in = new FileInputStream(file); -						states = new AltosEepromFile(in); +						record_set = new AltosEepromRecordSet(in);  					} else if (filename.endsWith("telem")) { -						FileInputStream in = new FileInputStream(file); -						states = new AltosTelemetryFile(in); +						record_set = new AltosTelemetryFile(in);  					} else {  						throw new FileNotFoundException(filename);  					}  					try { -						new AltosGraphUI(states, file); +						new AltosGraphUI(record_set, file);  					} catch (InterruptedException ie) {  					} catch (IOException ie) {  					} @@ -143,6 +142,11 @@ public class AltosLanded extends AltosUIFlightTab implements ActionListener {  								      fe.getMessage(),  								      "Cannot open file",  								      JOptionPane.ERROR_MESSAGE); +				} catch (IOException ie) { +					JOptionPane.showMessageDialog(null, +								      ie.getMessage(), +								      "Error reading file file", +								      JOptionPane.ERROR_MESSAGE);  				}  			}  		} diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java index d4e73b3e..f1893cf5 100644 --- a/altosui/AltosLaunch.java +++ b/altosui/AltosLaunch.java @@ -21,7 +21,7 @@ package altosui;  import java.io.*;  import java.util.concurrent.*;  import java.awt.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosLaunch {  	AltosDevice	device; diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 835858e2..8a24ed3e 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -24,7 +24,7 @@ import javax.swing.*;  import java.io.*;  import java.text.*;  import java.util.concurrent.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*;  class FireButton extends JButton {  	protected void processMouseEvent(MouseEvent e) { diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index d411c969..0aeef8e1 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -19,8 +19,8 @@  package altosui;  import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosPad extends AltosUIFlightTab { @@ -46,10 +46,11 @@ public class AltosPad extends AltosUIFlightTab {  	class LoggingReady extends AltosUIIndicator {  		public void show (AltosState state, AltosListenerState listener_state) { -			if (state == null || state.flight == AltosLib.MISSING) { +			AltosCalData	cal_data = state.cal_data(); +			if (state == null || cal_data.flight == AltosLib.MISSING) {  				hide();  			} else { -				if (state.flight != 0) { +				if (cal_data.flight != 0) {  					if (state.state() <= Altos.ao_flight_pad)  						show("Ready to record");  					else if (state.state() < Altos.ao_flight_landed || @@ -59,7 +60,7 @@ public class AltosPad extends AltosUIFlightTab {  						show("Recorded data");  				} else  					show("Storage full"); -				set_lights(state.flight != 0); +				set_lights(cal_data.flight != 0);  			}  		}  		public LoggingReady (AltosUIFlightTab container, int y) { @@ -128,10 +129,8 @@ public class AltosPad extends AltosUIFlightTab {  	}  	boolean report_pad(AltosState state) { -		if ((state.state() == AltosLib.ao_flight_stateless || -		     state.state() < AltosLib.ao_flight_pad) && -		    state.gps != null && -		    state.gps.lat != AltosLib.MISSING) +		if (state.state() == AltosLib.ao_flight_stateless || +		    state.state() < AltosLib.ao_flight_pad)  		{  			return false;  		} @@ -150,7 +149,7 @@ public class AltosPad extends AltosUIFlightTab {  				if (report_pad(state)) {  					lat = state.pad_lat;  					label = "Pad Latitude"; -				} else { +				} else if (state.gps != null) {  					lat = state.gps.lat;  					label = "Latitude";  				} @@ -187,7 +186,7 @@ public class AltosPad extends AltosUIFlightTab {  				if (report_pad(state)) {  					lon = state.pad_lon;  					label = "Pad Longitude"; -				} else { +				} else if (state.gps != null) {  					lon = state.gps.lon;  					label = "Longitude";  				} @@ -217,8 +216,10 @@ public class AltosPad extends AltosUIFlightTab {  		public double value(AltosState state, int i) {  			if (report_pad(state))  				return state.pad_alt; -			else +			else if (state.gps != null)  				return state.gps.alt; +			else +				return state.altitude();  		}  		public void show (AltosState state, AltosListenerState listener_state) { diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 019bbb9e..4bc2a5f8 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -23,8 +23,8 @@ import java.awt.event.*;  import javax.swing.*;  import java.io.*;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class AltosUI extends AltosUIFrame {  	public AltosVoice voice = new AltosVoice(); @@ -276,7 +276,7 @@ public class AltosUI extends AltosUIFrame {  	}  	void ConfigureTeleMetrum() { -		new AltosConfig(AltosUI.this); +		new AltosConfigFC(AltosUI.this);  	}  	void ConfigureTeleDongle() { @@ -310,10 +310,9 @@ public class AltosUI extends AltosUIFrame {  		AltosDataChooser chooser = new AltosDataChooser(  			AltosUI.this); -		Iterable<AltosState> states = chooser.runDialog(); -		if (states != null) { -			AltosFlightReader reader = new AltosReplayReader(states.iterator(), -									 chooser.file()); +		AltosRecordSet set = chooser.runDialog(); +		if (set != null) { +			AltosReplayReader reader = new AltosReplayReader(set, chooser.file());  			new AltosFlightUI(voice, reader);  		}  	} @@ -325,6 +324,13 @@ public class AltosUI extends AltosUIFrame {  		new AltosEepromManage(AltosUI.this, AltosLib.product_any);  	} +	private static AltosFlightSeries make_series(AltosRecordSet set) { +		AltosFlightSeries series = new AltosFlightSeries(set.cal_data()); +		set.capture_series(series); +		series.finish(); +		return series; +	} +  	/* Load a flight log file and write out a CSV file containing  	 * all of the data in standard units  	 */ @@ -332,10 +338,11 @@ public class AltosUI extends AltosUIFrame {  	private void ExportData() {  		AltosDataChooser chooser;  		chooser = new AltosDataChooser(this); -		AltosStateIterable states = chooser.runDialog(); -		if (states == null) +		AltosRecordSet set = chooser.runDialog(); +		if (set == null)  			return; -		new AltosCSVUI(AltosUI.this, states, chooser.file()); +		AltosFlightSeries series = make_series(set); +		new AltosCSVUI(AltosUI.this, series, chooser.file());  	}  	/* Load a flight log CSV file and display a pretty graph. @@ -344,11 +351,11 @@ public class AltosUI extends AltosUIFrame {  	private void GraphData() {  		AltosDataChooser chooser;  		chooser = new AltosDataChooser(this); -		AltosStateIterable states = chooser.runDialog(); -		if (states == null) +		AltosRecordSet set = chooser.runDialog(); +		if (set == null)  			return;  		try { -			new AltosGraphUI(states, chooser.file()); +			new AltosGraphUI(set, chooser.file());  		} catch (InterruptedException ie) {  		} catch (IOException ie) {  		} @@ -365,21 +372,6 @@ public class AltosUI extends AltosUIFrame {  		}  	} -	static AltosStateIterable open_logfile(File file) { -		try { -			FileInputStream in; - -			in = new FileInputStream(file); -			if (file.getName().endsWith("telem")) -				return new AltosTelemetryFile(in); -			else -				return new AltosEepromFile(in); -		} catch (FileNotFoundException fe) { -			System.out.printf("%s\n", fe.getMessage()); -			return null; -		} -	} -  	static AltosWriter open_csv(File file) {  		try {  			return new AltosCSV(file); @@ -398,17 +390,28 @@ public class AltosUI extends AltosUIFrame {  		}  	} +	static AltosRecordSet record_set(File input) { +		try { +			return AltosLib.record_set(input); +		} catch (IOException ie) { +			String message = ie.getMessage(); +			if (message == null) +				message = String.format("%s (I/O error)", input.toString()); +			System.err.printf("%s\n", message); +		} +		return null; +	} +  	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 final int process_summary = 5; -	static final int process_cat = 6;  	static boolean process_csv(File input) { -		AltosStateIterable states = open_logfile(input); -		if (states == null) +		AltosRecordSet set = record_set(input); +		if (set == null)  			return false;  		File output = Altos.replace_extension(input,".csv"); @@ -420,15 +423,16 @@ public class AltosUI extends AltosUIFrame {  			AltosWriter writer = open_csv(output);  			if (writer == null)  				return false; -			writer.write(states); +			AltosFlightSeries series = make_series(set); +			writer.write(series);  			writer.close();  		}  		return true;  	}  	static boolean process_kml(File input) { -		AltosStateIterable states = open_logfile(input); -		if (states == null) +		AltosRecordSet set = record_set(input); +		if (set == null)  			return false;  		File output = Altos.replace_extension(input,".kml"); @@ -440,31 +444,19 @@ public class AltosUI extends AltosUIFrame {  			AltosWriter writer = open_kml(output);  			if (writer == null)  				return false; -			writer.write(states); +			AltosFlightSeries series = make_series(set); +			series.finish(); +			writer.write(series);  			writer.close();  			return true;  		}  	} -	static AltosStateIterable record_iterable(File file) { -		FileInputStream in; -		try { -			in = new FileInputStream(file); -		} catch (Exception e) { -			System.out.printf("Failed to open file '%s'\n", file); -			return null; -		} -		if (file.getName().endsWith("telem")) -			return new AltosTelemetryFile(in); -		else -			return new AltosEepromFile(in); -	} -  	static AltosReplayReader replay_file(File file) { -		AltosStateIterable states = record_iterable(file); -		if (states == null) +		AltosRecordSet set = record_set(file); +		if (set == null)  			return null; -		return new AltosReplayReader(states.iterator(), file); +		return new AltosReplayReader(set, file);  	}  	static boolean process_replay(File file) { @@ -476,11 +468,11 @@ public class AltosUI extends AltosUIFrame {  	}  	static boolean process_graph(File file) { -		AltosStateIterable states = record_iterable(file); -		if (states == null) +		AltosRecordSet set = record_set(file); +		if (set == null)  			return false;  		try { -			new AltosGraphUI(states, file); +			new AltosGraphUI(set, file);  			return true;  		} catch (InterruptedException ie) {  		} catch (IOException ie) { @@ -489,85 +481,52 @@ public class AltosUI extends AltosUIFrame {  	}  	static boolean process_summary(File file) { -		AltosStateIterable states = record_iterable(file); -		if (states == null) -			return false; -		try { -			System.out.printf("%s:\n", file.toString()); -			AltosFlightStats stats = new AltosFlightStats(states); -			if (stats.serial != AltosLib.MISSING) -				System.out.printf("Serial:       %5d\n", stats.serial); -			if (stats.flight != AltosLib.MISSING) -				System.out.printf("Flight:       %5d\n", stats.flight); -			if (stats.year != AltosLib.MISSING) -				System.out.printf("Date:    %04d-%02d-%02d\n", -						  stats.year, stats.month, stats.day); -			if (stats.hour != AltosLib.MISSING) -				System.out.printf("Time:      %02d:%02d:%02d UTC\n", -						  stats.hour, stats.minute, stats.second); -			if (stats.max_height != AltosLib.MISSING) -				System.out.printf("Max height:  %6.0f m    %6.0f ft\n", -						  stats.max_height, -						  AltosConvert.meters_to_feet(stats.max_height)); -			if (stats.max_speed != AltosLib.MISSING) -				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 != AltosLib.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)); -			} -			if (stats.state_speed[Altos.ao_flight_drogue] != AltosLib.MISSING) -				System.out.printf("Drogue rate: %6.0f m/s  %6.0f ft/s\n", -						  stats.state_speed[Altos.ao_flight_drogue], -						  AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_drogue])); -			if (stats.state_speed[Altos.ao_flight_main] != AltosLib.MISSING) -				System.out.printf("Main rate:   %6.0f m/s  %6.0f ft/s\n", -						  stats.state_speed[Altos.ao_flight_main], -						  AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_main])); -			if (stats.state_end[Altos.ao_flight_main] != AltosLib.MISSING && -			    stats.state_start[Altos.ao_flight_boost] != AltosLib.MISSING) -				System.out.printf("Flight time: %6.0f s\n", -						  stats.state_end[Altos.ao_flight_main] - -						  stats.state_start[Altos.ao_flight_boost]); -			System.out.printf("\n"); -			return true; -		} catch (InterruptedException ie) { -		} catch (IOException ie) { -		} -		return false; -	} - -	static boolean process_cat(File file) { -		try { -			AltosStateIterable eef = record_iterable(file); - -			for (AltosState state : eef) { -				if ((state.set & AltosState.set_gps) != 0) { -					System.out.printf ("time %d %d-%d-%d %d:%d:%d lat %g lon %g alt %g\n", -							   state.gps.seconds(), -							   state.gps.year, -							   state.gps.month, -							   state.gps.day, -							   state.gps.hour, -							   state.gps.minute, -							   state.gps.second, -							   state.gps.lat, -							   state.gps.lon, -							   state.gps.alt); -				} else { -					System.out.printf ("tick %d state %d height %g\n", -							   state.tick, state.state(), state.height()); -				} -			} - -		} catch (Exception e) { -			System.out.printf("Failed to open file '%s'\n", file); +		AltosRecordSet set = record_set(file); +		if (set == null)  			return false; +		System.out.printf("%s:\n", file.toString()); +		AltosFlightSeries series = make_series(set); +		AltosFlightStats stats = new AltosFlightStats(series); +		if (stats.serial != AltosLib.MISSING) +			System.out.printf("Serial:       %5d\n", stats.serial); +		if (stats.flight != AltosLib.MISSING) +			System.out.printf("Flight:       %5d\n", stats.flight); +		if (stats.year != AltosLib.MISSING) +			System.out.printf("Date:    %04d-%02d-%02d\n", +					  stats.year, stats.month, stats.day); +		if (stats.hour != AltosLib.MISSING) +			System.out.printf("Time:      %02d:%02d:%02d UTC\n", +					  stats.hour, stats.minute, stats.second); +		if (stats.max_height != AltosLib.MISSING) +			System.out.printf("Max height:  %6.0f m    %6.0f ft\n", +					  stats.max_height, +					  AltosConvert.meters_to_feet(stats.max_height)); +		if (stats.max_speed != AltosLib.MISSING) +			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 != AltosLib.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));  		} +		if (stats.state_speed[Altos.ao_flight_drogue] != AltosLib.MISSING) +			System.out.printf("Drogue rate: %6.0f m/s  %6.0f ft/s\n", +					  stats.state_speed[Altos.ao_flight_drogue], +					  AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_drogue])); +		if (stats.state_speed[Altos.ao_flight_main] != AltosLib.MISSING) +			System.out.printf("Main rate:   %6.0f m/s  %6.0f ft/s\n", +					  stats.state_speed[Altos.ao_flight_main], +					  AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_main])); +		if (stats.landed_time != AltosLib.MISSING && +		    stats.boost_time != AltosLib.MISSING && +		    stats.landed_time > stats.boost_time) +			System.out.printf("Flight time: %6.0f s\n", +					  stats.landed_time - +					  stats.boost_time); +		System.out.printf("\n");  		return true;  	} @@ -613,8 +572,6 @@ public class AltosUI extends AltosUIFrame {  					process = process_graph;  				else if (args[i].equals("--summary"))  					process = process_summary; -				else if (args[i].equals("--cat")) -					process = process_cat;  				else if (args[i].startsWith("--"))  					help(1);  				else { @@ -643,9 +600,6 @@ public class AltosUI extends AltosUIFrame {  						if (!process_summary(file))  							++errors;  						break; -					case process_cat: -						if (!process_cat(file)) -							++errors;  					}  				}  			} diff --git a/altosui/Makefile-standalone b/altosui/Makefile-standalone index cbaf9743..e5f41639 100644 --- a/altosui/Makefile-standalone +++ b/altosui/Makefile-standalone @@ -4,8 +4,8 @@ CLASSPATH=classes:./*:/usr/share/java/*  CLASSFILES=\  	Altos.class \  	AltosChannelMenu.class \ -	AltosConfig.class \ -	AltosConfigUI.class \ +	AltosConfigFC.class \ +	AltosConfigFCUI.class \  	AltosConvert.class \  	AltosCRCException.class \  	AltosCSV.class \ diff --git a/altosui/Makefile.am b/altosui/Makefile.am index de3dee68..31ec06bc 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -14,8 +14,8 @@ altosui_JAVA = \  	AltosAscent.java \  	AltosChannelMenu.java \  	AltosCompanionInfo.java \ -	AltosConfig.java \ -	AltosConfigUI.java \ +	AltosConfigFC.java \ +	AltosConfigFCUI.java \  	AltosConfigPyroUI.java \  	AltosConfigureUI.java \  	AltosConfigTD.java \ @@ -131,11 +131,13 @@ FIRMWARE_TM_2_0=$(top_srcdir)/src/telemetrum-v2.0/telemetrum-v2.0-$(VERSION).ihx  FIRMWARE_TM=$(FIRMWARE_TM_1_0) $(FIRMWARE_TM_1_1) $(FIRMWARE_TM_1_2) $(FIRMWARE_TM_2_0)  FIRMWARE_TELEMINI_1_0=$(top_srcdir)/src/telemini-v1.0/telemini-v1.0-$(VERSION).ihx -FIRMWARE_TELEMINI=$(FIRMWARE_TELEMINI_1_0) +FIRMWARE_TELEMINI_3_0=$(top_srcdir)/src/telemini-v3.0/telemini-v3.0-$(VERSION).ihx +FIRMWARE_TELEMINI=$(FIRMWARE_TELEMINI_1_0) $(FIRMWARE_TELEMINI_3_0)  FIRMWARE_TBT_1_0=$(top_srcdir)/src/telebt-v1.0/telebt-v1.0-$(VERSION).ihx  FIRMWARE_TBT_3_0=$(top_srcdir)/src/telebt-v3.0/telebt-v3.0-$(VERSION).ihx -FIRMWARE_TBT=$(FIRMWARE_TBT_1_0) $(FIRMWARE_TBT_3_0) +FIRMWARE_TBT_4_0=$(top_srcdir)/src/telebt-v4.0/telebt-v4.0-$(VERSION).ihx +FIRMWARE_TBT=$(FIRMWARE_TBT_1_0) $(FIRMWARE_TBT_3_0) $(FIRMWARE_TBT_4_0)  FIRMWARE_TMEGA_1_0=$(top_srcdir)/src/telemega-v1.0/telemega-v1.0-$(VERSION).ihx  FIRMWARE_TMEGA_2_0=$(top_srcdir)/src/telemega-v2.0/telemega-v2.0-$(VERSION).ihx diff --git a/altosui/altos-windows.nsi.in b/altosui/altos-windows.nsi.in index 1039bd41..31139513 100644 --- a/altosui/altos-windows.nsi.in +++ b/altosui/altos-windows.nsi.in @@ -126,14 +126,17 @@ Section "Firmware"  	File "../src/telemetrum-v2.0/telemetrum-v2.0-${VERSION}.ihx"  ;	File "../src/telemetrum-v3.0/telemetrum-v3.0-${VERSION}.ihx"  	File "../src/telemini-v1.0/telemini-v1.0-${VERSION}.ihx" +	File "../src/telemini-v3.0/telemini-v3.0-${VERSION}.ihx"  	File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"  	File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"  	File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"  	File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"  	File "../src/telebt-v3.0/telebt-v3.0-${VERSION}.ihx" +	File "../src/telebt-v4.0/telebt-v4.0-${VERSION}.ihx"  	File "../src/telemega-v1.0/telemega-v1.0-${VERSION}.ihx"  	File "../src/telemega-v2.0/telemega-v2.0-${VERSION}.ihx"  	File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx" +	File "../src/easymini-v2.0/easymini-v2.0-${VERSION}.ihx"  	File "../src/easymega-v1.0/easymega-v1.0-${VERSION}.ihx"  SectionEnd diff --git a/altosuilib/AltosBTDevice.java b/altosuilib/AltosBTDevice.java index 313cf0a0..5b9ab06a 100644 --- a/altosuilib/AltosBTDevice.java +++ b/altosuilib/AltosBTDevice.java @@ -16,10 +16,10 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosBTDevice extends altos_bt_device implements AltosDevice { diff --git a/altosuilib/AltosBTDeviceIterator.java b/altosuilib/AltosBTDeviceIterator.java index 1ea31950..ac9068d0 100644 --- a/altosuilib/AltosBTDeviceIterator.java +++ b/altosuilib/AltosBTDeviceIterator.java @@ -16,11 +16,11 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.util.*;  import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {  	AltosBTDevice	current; diff --git a/altosuilib/AltosBTKnown.java b/altosuilib/AltosBTKnown.java index 32cc05d7..56f1991f 100644 --- a/altosuilib/AltosBTKnown.java +++ b/altosuilib/AltosBTKnown.java @@ -16,10 +16,10 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosBTKnown implements Iterable<AltosBTDevice> {  	LinkedList<AltosBTDevice>	devices = new LinkedList<AltosBTDevice>(); diff --git a/altosuilib/AltosBTManage.java b/altosuilib/AltosBTManage.java index 14e0a056..aec4c34d 100644 --- a/altosuilib/AltosBTManage.java +++ b/altosuilib/AltosBTManage.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*; @@ -24,7 +24,7 @@ import javax.swing.*;  import javax.swing.plaf.basic.*;  import java.util.*;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> {  	LinkedBlockingQueue<AltosBTDevice> found_devices; diff --git a/altosuilib/AltosCSVUI.java b/altosuilib/AltosCSVUI.java index 1b769740..442e3de3 100644 --- a/altosuilib/AltosCSVUI.java +++ b/altosuilib/AltosCSVUI.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*;  import java.io.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosCSVUI  	extends AltosUIDialog @@ -31,7 +31,8 @@ public class AltosCSVUI  	JFileChooser		csv_chooser;  	JPanel			accessory;  	JComboBox<String>	combo_box; -	Iterable<AltosState>	states; +	AltosFlightSeries	series; +	AltosCalData		cal_data;  	AltosWriter		writer;  	static String[]		combo_box_items = { "Comma Separated Values (.CSV)", "Googleearth Data (.KML)" }; @@ -55,8 +56,9 @@ public class AltosCSVUI  			set_default_file();  	} -	public AltosCSVUI(JFrame frame, AltosStateIterable states, File source_file) { -		this.states = states; +	public AltosCSVUI(JFrame frame, AltosFlightSeries series, File source_file) { +		this.series = series; +		this.cal_data = series.cal_data();  		csv_chooser = new JFileChooser(source_file);  		accessory = new JPanel(); @@ -91,7 +93,7 @@ public class AltosCSVUI  					writer = new AltosCSV(file);  				else  					writer = new AltosKML(file); -				writer.write(states); +				writer.write(series);  				writer.close();  			} catch (FileNotFoundException ee) {  				JOptionPane.showMessageDialog(frame, diff --git a/altosuilib/AltosConfigFreqUI.java b/altosuilib/AltosConfigFreqUI.java index c4d2abba..055d34f9 100644 --- a/altosuilib/AltosConfigFreqUI.java +++ b/altosuilib/AltosConfigFreqUI.java @@ -16,14 +16,14 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.text.*;  import java.awt.event.*;  import javax.swing.*;  import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  class AltosEditFreqUI extends AltosUIDialog implements ActionListener {  	Frame		frame; diff --git a/altosuilib/AltosDataChooser.java b/altosuilib/AltosDataChooser.java index 8758fc34..b417c732 100644 --- a/altosuilib/AltosDataChooser.java +++ b/altosuilib/AltosDataChooser.java @@ -16,12 +16,12 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import javax.swing.*;  import javax.swing.filechooser.FileNameExtensionFilter;  import java.io.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosDataChooser extends JFileChooser {  	JFrame	frame; @@ -36,7 +36,7 @@ public class AltosDataChooser extends JFileChooser {  		return file;  	} -	public AltosStateIterable runDialog() { +	public AltosRecordSet runDialog() {  		int	ret;  		ret = showOpenDialog(frame); @@ -44,21 +44,12 @@ public class AltosDataChooser extends JFileChooser {  			file = getSelectedFile();  			if (file == null)  				return null; -			filename = file.getName();  			try { -				if (filename.endsWith("eeprom")) { -					FileInputStream in = new FileInputStream(file); -					return new AltosEepromFile(in); -				} else if (filename.endsWith("telem")) { -					FileInputStream in = new FileInputStream(file); -					return new AltosTelemetryFile(in); -				} else { -					throw new FileNotFoundException(); -				} -			} catch (FileNotFoundException fe) { +				return AltosLib.record_set(file); +			} catch (IOException ie) {  				JOptionPane.showMessageDialog(frame, -							      fe.getMessage(), -							      "Cannot open file", +							      ie.getMessage(), +							      "Error reading file",  							      JOptionPane.ERROR_MESSAGE);  			}  		} diff --git a/altosuilib/AltosDevice.java b/altosuilib/AltosDevice.java index f9878fe9..44f71f7a 100644 --- a/altosuilib/AltosDevice.java +++ b/altosuilib/AltosDevice.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import libaltosJNI.*; diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java index 5d8ff570..77249bfc 100644 --- a/altosuilib/AltosDeviceDialog.java +++ b/altosuilib/AltosDeviceDialog.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import javax.swing.*;  import java.awt.*; diff --git a/altosuilib/AltosDeviceUIDialog.java b/altosuilib/AltosDeviceUIDialog.java index c2d6f4f3..f3409cce 100644 --- a/altosuilib/AltosDeviceUIDialog.java +++ b/altosuilib/AltosDeviceUIDialog.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import javax.swing.*;  import java.awt.*; diff --git a/altosuilib/AltosDisplayThread.java b/altosuilib/AltosDisplayThread.java index 52414c62..3fcc02da 100644 --- a/altosuilib/AltosDisplayThread.java +++ b/altosuilib/AltosDisplayThread.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import javax.swing.*;  import java.io.*;  import java.text.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosDisplayThread extends Thread { @@ -30,7 +30,9 @@ public class AltosDisplayThread extends Thread {  	IdleThread		idle_thread;  	AltosVoice		voice;  	AltosFlightReader	reader; -	AltosState		old_state, state; +	AltosState		state; +	int			old_state = AltosLib.ao_flight_invalid; +	boolean			old_gps_ready = false;  	AltosListenerState	listener_state;  	AltosFlightDisplay	display; @@ -93,13 +95,13 @@ public class AltosDisplayThread extends Thread {  			    state.from_pad != null &&  			    state.range >= 0)  			{ -				voice.speak("Height %s, bearing %s %d, elevation %d, range %s.\n", +				voice.speak("Height %s, bearing %s %d, elevation %d, distance %s.\n",  					    AltosConvert.height.say(state.height()),  					    state.from_pad.bearing_words(  						    AltosGreatCircle.BEARING_VOICE),  					    (int) (state.from_pad.bearing + 0.5),  					    (int) (state.elevation + 0.5), -					    AltosConvert.distance.say(state.range)); +					    AltosConvert.distance.say(state.distance));  			} else if (state.state() > AltosLib.ao_flight_pad && state.height() != AltosLib.MISSING) {  				voice.speak(AltosConvert.height.say_units(state.height()));  			} else { @@ -121,7 +123,7 @@ public class AltosDisplayThread extends Thread {  				else  					voice.speak("rocket may have crashed");  				if (state.from_pad != null) -					voice.speak("Bearing %d degrees, range %s.", +					voice.speak("Bearing %d degrees, distance %s.",  						    (int) (state.from_pad.bearing + 0.5),  						    AltosConvert.distance.say_units(state.from_pad.distance));  				++reported_landing; @@ -164,7 +166,7 @@ public class AltosDisplayThread extends Thread {  		}  		public synchronized void notice(boolean spoken) { -			if (old_state != null && old_state.state() != state.state()) { +			if (old_state != state.state()) {  				report_time = now();  				this.notify();  			} else if (spoken) @@ -179,16 +181,16 @@ public class AltosDisplayThread extends Thread {  	synchronized boolean tell() {  		boolean	ret = false; -		if (old_state == null || old_state.state() != state.state()) { +		if (old_state != state.state()) {  			if (state.state() != AltosLib.ao_flight_stateless)  				voice.speak(state.state_name()); -			if ((old_state == null || old_state.state() <= AltosLib.ao_flight_boost) && +			if ((old_state == AltosLib.ao_flight_invalid || old_state <= AltosLib.ao_flight_boost) &&  			    state.state() > AltosLib.ao_flight_boost) {  				if (state.max_speed() != AltosLib.MISSING)  					voice.speak("max speed: %s.",  						    AltosConvert.speed.say_units(state.max_speed() + 0.5));  				ret = true; -			} else if ((old_state == null || old_state.state() < AltosLib.ao_flight_drogue) && +			} else if ((old_state == AltosLib.ao_flight_invalid || old_state < AltosLib.ao_flight_drogue) &&  				   state.state() >= AltosLib.ao_flight_drogue) {  				if (state.max_height() != AltosLib.MISSING)  					voice.speak("max height: %s.", @@ -196,17 +198,18 @@ public class AltosDisplayThread extends Thread {  				ret = true;  			}  		} -		if (old_state == null || old_state.gps_ready != state.gps_ready) { +		if (old_gps_ready != state.gps_ready) {  			if (state.gps_ready) {  				voice.speak("GPS ready");  				ret = true;  			} -			else if (old_state != null) { +			else if (old_gps_ready) {  				voice.speak("GPS lost");  				ret = true;  			}  		} -		old_state = state; +		old_state = state.state(); +		old_gps_ready = state.gps_ready;  		return ret;  	} @@ -220,14 +223,11 @@ public class AltosDisplayThread extends Thread {  		try {  			for (;;) {  				try { -					AltosState new_state = reader.read(); -					if (new_state == null) { -						state = null; +					state = reader.read(); +					if (state == null) {  						listener_state.running = false;  						break;  					} -					reader.update(new_state); -					state = new_state;  					show_safely();  					told = tell();  					idle_thread.notice(told); diff --git a/altosuilib/AltosEepromDelete.java b/altosuilib/AltosEepromDelete.java index 24337be4..87e80a51 100644 --- a/altosuilib/AltosEepromDelete.java +++ b/altosuilib/AltosEepromDelete.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.event.*;  import javax.swing.*;  import java.io.*;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosEepromDelete implements Runnable {  	AltosEepromList		flights; diff --git a/altosuilib/AltosEepromManage.java b/altosuilib/AltosEepromManage.java index a6636c4f..93827139 100644 --- a/altosuilib/AltosEepromManage.java +++ b/altosuilib/AltosEepromManage.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.event.*;  import javax.swing.*;  import java.io.*;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosEepromManage implements ActionListener { diff --git a/altosuilib/AltosEepromMonitor.java b/altosuilib/AltosEepromMonitor.java deleted file mode 100644 index d61169f4..00000000 --- a/altosuilib/AltosEepromMonitor.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright © 2010 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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. - */ - -package org.altusmetrum.altosuilib_11; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -public class AltosEepromMonitor extends AltosUIDialog { - -	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(1000); -		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); -	} - -	private void set_value_internal(String state_name, int state, int state_block, int block) { -		if (state_block > 100) -			state_block = 100; -		if (state < min_state) state = min_state; -		if (state >= max_state) state = max_state - 1; -		state -= min_state; - -		int pos = state * 100 + state_block; - -		pbar.setString(String.format("block %d state %s", block, state_name)); -		pbar.setValue(pos); -	} - -	public void set_value(String in_state_name, int in_state, int in_state_block, int in_block) { -		final String state_name = in_state_name; -		final int state = in_state; -		final int state_block = in_state_block; -		final int block = in_block; -		Runnable r = new Runnable() { -				public void run() { -					try { -						set_value_internal(state_name, state, state_block, block); -					} catch (Exception ex) { -					} -				} -			}; -		SwingUtilities.invokeLater(r); -	} - -	private void set_serial_internal(int serial) { -		serial_value.setText(String.format("%d", serial)); -	} - -	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_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 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); -	} - -	private void reset_internal() { -		set_value_internal("startup",min_state,0, 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/altosuilib/AltosEepromMonitorUI.java b/altosuilib/AltosEepromMonitorUI.java index d708ae96..3427fe0f 100644 --- a/altosuilib/AltosEepromMonitorUI.java +++ b/altosuilib/AltosEepromMonitorUI.java @@ -16,12 +16,12 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {  	JFrame		owner; @@ -35,7 +35,6 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo  	JLabel		file_value;  	JButton		cancel;  	JProgressBar	pbar; -	int		min_state, max_state;  	ActionListener	listener;  	static final int	progress_max = 10000; @@ -138,11 +137,6 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo  		listener = l;  	} -	public void set_states(int min_state, int max_state) { -		this.min_state = min_state; -		this.max_state = max_state; -	} -  	public void set_thread(Thread in_eeprom_thread) {  		final Thread eeprom_thread = in_eeprom_thread;  		cancel.addActionListener(new ActionListener() { @@ -157,52 +151,30 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo  		setVisible(true);  	} -	private void set_value_internal(String state_name, int state, int state_block, int block) { +	int max_block = 1; + +	public void set_block_internal(int block) {  		double	pos;  		String	s; -		if (min_state == AltosLib.ao_flight_invalid) { -			int	lblock = block; -			if (lblock > 1000) -				lblock = 1000; -			pos = lblock / 1000.0; -			s = String.format("block %d", block); -		} else { -			if (state == AltosLib.ao_flight_invalid) -				state = 0; -			if (state_block > 100) -				state_block = 100; -			if (state < min_state) state = min_state; -			if (state > max_state) state = max_state; - -			if (state == max_state) -				state_block = 0; - -			state -= min_state; - -			int	nstate = max_state - min_state; +		pos = (double) block / (double) max_block; -			double	spos = (double) state / (double) nstate; -			double	bpos = state_block / 100.0; - -			pos = spos + bpos / nstate; - -			s = String.format("block %d state %s", block, state_name); -		} +		s = String.format("block %d of %d", block, max_block);  		pbar.setString(s);  		pbar.setValue((int) (pos * progress_max));  	} -	public void set_value(String in_state_name, int in_state, int in_state_block, int in_block) { -		final String state_name = in_state_name; -		final int state = in_state; -		final int state_block = in_state_block; +	public void set_max(int max_block) { +		this.max_block = max_block; +	} + +	public void set_block(int in_block) {  		final int block = in_block;  		Runnable r = new Runnable() {  				public void run() {  					try { -						set_value_internal(state_name, state, state_block, block); +						set_block_internal(block);  					} catch (Exception ex) {  					}  				} @@ -283,7 +255,8 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo  	}  	private void reset_internal() { -		set_value_internal("startup",min_state,0, 0); +		set_max(1); +		set_block_internal(0);  		set_flight_internal(0);  		set_filename_internal("");  	} diff --git a/altosuilib/AltosEepromSelect.java b/altosuilib/AltosEepromSelect.java index 0b4b7a85..0c890c8b 100644 --- a/altosuilib/AltosEepromSelect.java +++ b/altosuilib/AltosEepromSelect.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import javax.swing.*;  import javax.swing.border.*;  import java.awt.*;  import java.awt.event.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  class AltosEepromItem implements ActionListener {  	AltosEepromLog	log; @@ -38,11 +38,7 @@ class AltosEepromItem implements ActionListener {  		log = in_log;  		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); +		text = String.format("Flight #%02d", log.flight);  		label = new JLabel(text); diff --git a/altosuilib/AltosFlashUI.java b/altosuilib/AltosFlashUI.java index da36397a..ca089ca8 100644 --- a/altosuilib/AltosFlashUI.java +++ b/altosuilib/AltosFlashUI.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*; @@ -24,7 +24,7 @@ import javax.swing.*;  import javax.swing.filechooser.FileNameExtensionFilter;  import java.io.*;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosFlashUI  	extends AltosUIDialog diff --git a/altosuilib/AltosFlightInfoTableModel.java b/altosuilib/AltosFlightInfoTableModel.java index 2d371101..943c9207 100644 --- a/altosuilib/AltosFlightInfoTableModel.java +++ b/altosuilib/AltosFlightInfoTableModel.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import javax.swing.table.*; diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java index 2f46f231..415c0244 100644 --- a/altosuilib/AltosFlightStatsTable.java +++ b/altosuilib/AltosFlightStatsTable.java @@ -16,12 +16,12 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import javax.swing.*;  import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosFlightStatsTable extends JComponent implements AltosFontListener {  	GridBagLayout	layout; @@ -87,13 +87,19 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen  		return String.format("%s %4d° %9.6f'", h, deg, min);  	} -	public AltosFlightStatsTable(AltosFlightStats stats) { -		layout = new GridBagLayout(); - -		setLayout(layout); +	public void set_stats(AltosFlightStats stats) {  		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.serial != AltosLib.MISSING) { +			if (stats.product != null && stats.firmware_version != null) +				new FlightStat(layout, y++, "Device", +					       stats.product, +					       String.format("version %s", stats.firmware_version), +					       String.format("serial %d", stats.serial)); +			else +				new FlightStat(layout, y++, "Serial", String.format("%d", stats.serial)); +		} +		if (stats.flight != AltosLib.MISSING) +			new FlightStat(layout, y++, "Flight", String.format("%d", stats.flight));  		if (stats.year != AltosLib.MISSING && stats.hour != AltosLib.MISSING)  			new FlightStat(layout, y++, "Date/Time",  				       String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day), @@ -108,61 +114,112 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen  		}  		if (stats.max_height != AltosLib.MISSING) {  			new FlightStat(layout, y++, "Maximum height", -				       String.format("%5.0f m", stats.max_height), +				       String.format("%6.1f m", stats.max_height),  				       String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));  		}  		if (stats.max_gps_height != AltosLib.MISSING) {  			new FlightStat(layout, y++, "Maximum GPS height", -				       String.format("%5.0f m", stats.max_gps_height), +				       String.format("%6.1f m", stats.max_gps_height),  				       String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_gps_height)));  		} -		new FlightStat(layout, y++, "Maximum speed", -			       String.format("%5.0f m/s", stats.max_speed), -			       String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)), -			       String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); +		if (stats.max_speed != AltosLib.MISSING) { +			new FlightStat(layout, y++, "Maximum speed", +				       String.format("%6.1f m/s", stats.max_speed), +				       String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)), +				       String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); +		}  		if (stats.max_acceleration != AltosLib.MISSING)  			new FlightStat(layout, y++, "Maximum boost acceleration", -				       String.format("%5.0f m/s²", stats.max_acceleration), +				       String.format("%6.1f m/s²", stats.max_acceleration),  				       String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)), -				       String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_acceleration))); +				       String.format("%6.2f G", AltosConvert.meters_to_g(stats.max_acceleration)));  		if (stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING)  			new FlightStat(layout, y++, "Average boost acceleration", -				       String.format("%5.0f m/s²", stats.state_accel[AltosLib.ao_flight_boost]), +				       String.format("%6.1f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),  				       String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])), -				       String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost]))); -		if (stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING) -			new FlightStat(layout, y++, "Drogue descent rate", -				       String.format("%5.0f m/s", stats.state_speed[AltosLib.ao_flight_drogue]), -				       String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_drogue]))); +				       String.format("%6.2f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost]))); +		if (stats.state_time[AltosLib.ao_flight_boost] != 0 || stats.state_time[AltosLib.ao_flight_fast] != 0 || stats.state_time[AltosLib.ao_flight_coast] != 0) { + +			double	boost_time = stats.state_time[AltosLib.ao_flight_boost]; +			double	fast_time = stats.state_time[AltosLib.ao_flight_fast]; +			double	coast_time = stats.state_time[AltosLib.ao_flight_coast]; + +			if (fast_time > 0) { +				new FlightStat(layout, y++, "Ascent time", +					       String.format("%6.1f s %s", boost_time, +							     AltosLib.state_name(AltosLib.ao_flight_boost)), +					       String.format("%6.1f s %s", fast_time, +							     AltosLib.state_name(AltosLib.ao_flight_fast)), +					       String.format("%6.1f s %s", coast_time, +							     AltosLib.state_name(AltosLib.ao_flight_coast))); +			} else { +				new FlightStat(layout, y++, "Ascent time", +					       String.format("%6.1f s %s", boost_time, +							     AltosLib.state_name(AltosLib.ao_flight_boost)), +					       String.format("%6.1f s %s", coast_time, +							     AltosLib.state_name(AltosLib.ao_flight_coast))); +			} +		} +		if (stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING) { +			String	label; + +			if (stats.state_speed[AltosLib.ao_flight_main] == AltosLib.MISSING) +				label = "Descent rate"; +			else +				label = "Drogue descent rate"; +			new FlightStat(layout, y++, label, +				       String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_drogue]), +				       String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_drogue]))); +		}  		if (stats.state_speed[AltosLib.ao_flight_main] != AltosLib.MISSING)  			new FlightStat(layout, y++, "Main descent rate", -				       String.format("%5.0f m/s", stats.state_speed[AltosLib.ao_flight_main]), -				       String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main]))); -		if (stats.state_start[AltosLib.ao_flight_boost] < stats.state_end[AltosLib.ao_flight_coast]) -			new FlightStat(layout, y++, "Ascent time", -				       String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost], -						     AltosLib.state_name(AltosLib.ao_flight_boost)), -				       String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast], -						     AltosLib.state_name(AltosLib.ao_flight_fast)), -				       String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast], -						     AltosLib.state_name(AltosLib.ao_flight_coast))); -		if (stats.state_start[AltosLib.ao_flight_drogue] < stats.state_end[AltosLib.ao_flight_main]) -			new FlightStat(layout, y++, "Descent time", -				       String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue], -						     AltosLib.state_name(AltosLib.ao_flight_drogue)), -				       String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_main] - stats.state_start[AltosLib.ao_flight_main], -						     AltosLib.state_name(AltosLib.ao_flight_main))); -		if (stats.state_start[AltosLib.ao_flight_boost] < stats.state_end[AltosLib.ao_flight_main]) +				       String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_main]), +				       String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main]))); +		if (stats.state_time[AltosLib.ao_flight_drogue] != 0 || stats.state_time[AltosLib.ao_flight_main] != 0) { +			double	drogue_duration = stats.state_time[AltosLib.ao_flight_drogue]; +			double	main_duration = stats.state_time[AltosLib.ao_flight_main]; +			double	duration = drogue_duration + main_duration; + +			if (drogue_duration > 0 && main_duration > 0) { +				new FlightStat(layout, y++, "Descent time", +					       String.format("%6.1f s %s", drogue_duration, +							     AltosLib.state_name(AltosLib.ao_flight_drogue)), +					       String.format("%6.1f s %s", main_duration, +							     AltosLib.state_name(AltosLib.ao_flight_main))); +			} else if (duration > 0) { +				new FlightStat(layout, y++, "Descent time", +					       String.format("%6.1f s", duration)); +			} +		} +		if (stats.landed_time > stats.boost_time)  			new FlightStat(layout, y++, "Flight time", -				       String.format("%6.1f s", stats.state_end[AltosLib.ao_flight_main] - -						     stats.state_start[AltosLib.ao_flight_boost])); -		if (stats.has_gps) { +				       String.format("%6.1f s", stats.landed_time - stats.boost_time)); +		if (stats.has_gps && stats.pad_lat != AltosLib.MISSING) {  			new FlightStat(layout, y++, "Pad location",  				       pos(stats.pad_lat,"N","S"),  				       pos(stats.pad_lon,"E","W")); +		} +		if (stats.has_gps && stats.lat != AltosLib.MISSING) {  			new FlightStat(layout, y++, "Last reported location",  				       pos(stats.lat,"N","S"),  				       pos(stats.lon,"E","W"));  		}  	} + +	public void tell_closing() { +		AltosUIPreferences.unregister_font_listener(this); +	} + +	public AltosFlightStatsTable() { +		layout = new GridBagLayout(); + +		setLayout(layout); + +		AltosUIPreferences.register_font_listener(this); +	} + +	public AltosFlightStatsTable(AltosFlightStats stats) { +		this(); +		set_stats(stats); +	}  } diff --git a/altosuilib/AltosGraph.java b/altosuilib/AltosGraph.java index 23fa1ffe..31042abb 100644 --- a/altosuilib/AltosGraph.java +++ b/altosuilib/AltosGraph.java @@ -16,14 +16,14 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.io.*;  import java.util.ArrayList;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import org.jfree.ui.*;  import org.jfree.chart.*; @@ -35,185 +35,32 @@ import org.jfree.chart.labels.*;  import org.jfree.data.xy.*;  import org.jfree.data.*; -class AltosVoltage extends AltosUnits { - -	public double value(double v, boolean imperial_units) { -		return v; -	} - -	public double inverse(double v, boolean imperial_units) { -		return v; -	} - -	public String show_units(boolean imperial_units) { -		return "V"; -	} - -	public String say_units(boolean imperial_units) { -		return "volts"; -	} - -	public int show_fraction(int width, boolean imperial_units) { -		return width / 2; -	} -} - -class AltosNsat extends AltosUnits { - -	public double value(double v, boolean imperial_units) { -		return v; -	} - -	public double inverse(double v, boolean imperial_units) { -		return v; -	} - -	public String show_units(boolean imperial_units) { -		return "Sats"; -	} - -	public String say_units(boolean imperial_units) { -		return "Satellites"; -	} - -	public int show_fraction(int width, boolean imperial_units) { -		return 0; -	} -} - -class AltosPressure extends AltosUnits { - -	public double value(double p, boolean imperial_units) { -		return p; -	} - -	public double inverse(double p, boolean imperial_units) { -		return p; -	} - -	public String show_units(boolean imperial_units) { -		return "Pa"; -	} - -	public String say_units(boolean imperial_units) { -		return "pascals"; -	} - -	public int show_fraction(int width, boolean imperial_units) { -		return 0; -	} -} - -class AltosDbm extends AltosUnits { - -	public double value(double d, boolean imperial_units) { -		return d; -	} - -	public double inverse(double d, boolean imperial_units) { -		return d; -	} - -	public String show_units(boolean imperial_units) { -		return "dBm"; -	} - -	public String say_units(boolean imperial_units) { -		return "D B M"; -	} - -	public int show_fraction(int width, boolean imperial_units) { -		return 0; -	} -} - -class AltosGyroUnits extends AltosUnits { - -	public double value(double p, boolean imperial_units) { -		return p; -	} - -	public double inverse(double p, boolean imperial_units) { -		return p; -	} - -	public String show_units(boolean imperial_units) { -		return "°/sec"; -	} - -	public String say_units(boolean imperial_units) { -		return "degrees per second"; -	} - -	public int show_fraction(int width, boolean imperial_units) { -		return 1; -	} -} - -class AltosMagUnits extends AltosUnits { - -	public double value(double p, boolean imperial_units) { -		return p; -	} - -	public double inverse(double p, boolean imperial_units) { -		return p; -	} - -	public String show_units(boolean imperial_units) { -		return "Ga"; -	} - -	public String say_units(boolean imperial_units) { -		return "gauss"; -	} - -	public int show_fraction(int width, boolean imperial_units) { -		return 2; -	} -} - -class AltosDopUnits extends AltosUnits { - -	public double value(double p, boolean imperial_units) { -		return p; -	} - -	public double inverse(double p, boolean imperial_units) { -		return p; -	} - -	public String show_units(boolean imperial_units) { -		return null; -	} - -	public String say_units(boolean imperial_units) { -		return null; -	} - -	public int show_fraction(int width, boolean imperial_units) { -		return 1; -	} -} -  public class AltosGraph extends AltosUIGraph {  	static final private Color height_color = new Color(194,31,31); +	static final private Color kalman_height_color = new Color(255,0,0);  	static final private Color gps_height_color = new Color(150,31,31);  	static final private Color pressure_color = new Color (225,31,31);  	static final private Color range_color = new Color(100, 31, 31);  	static final private Color distance_color = new Color(100, 31, 194);  	static final private Color speed_color = new Color(31,194,31); +	static final private Color kalman_speed_color = new Color(0,255,0); +	static final private Color thrust_color = new Color(31,194,31);  	static final private Color accel_color = new Color(31,31,194); +	static final private Color vert_accel_color = new Color(64,164,164); +	static final private Color kalman_accel_color = new Color(0,0,255);  	static final private Color voltage_color = new Color(194, 194, 31);  	static final private Color battery_voltage_color = new Color(194, 194, 31);  	static final private Color drogue_voltage_color = new Color(150, 150, 31);  	static final private Color main_voltage_color = new Color(100, 100, 31); +	static final private Color igniter_voltage_color = new Color(80, 80, 31); +	static final private Color igniter_marker_color = new Color(255, 0, 0);  	static final private Color gps_nsat_color = new Color (194, 31, 194);  	static final private Color gps_nsat_solution_color = new Color (194, 31, 194);  	static final private Color gps_nsat_view_color = new Color (150, 31, 150);  	static final private Color gps_course_color = new Color (100, 31, 112);  	static final private Color gps_ground_speed_color = new Color (31, 112, 100); +	static final private Color gps_speed_color = new Color (31, 112, 100);  	static final private Color gps_climb_rate_color = new Color (31, 31, 112);  	static final private Color gps_pdop_color = new Color(50, 194, 0);  	static final private Color gps_hdop_color = new Color(50, 0, 194); @@ -221,278 +68,268 @@ public class AltosGraph extends AltosUIGraph {  	static final private Color temperature_color = new Color (31, 194, 194);  	static final private Color dbm_color = new Color(31, 100, 100);  	static final private Color state_color = new Color(0,0,0); -	static final private Color accel_x_color = new Color(255, 0, 0); -	static final private Color accel_y_color = new Color(0, 255, 0); -	static final private Color accel_z_color = new Color(0, 0, 255); -	static final private Color gyro_x_color = new Color(192, 0, 0); -	static final private Color gyro_y_color = new Color(0, 192, 0); -	static final private Color gyro_z_color = new Color(0, 0, 192); -	static final private Color mag_x_color = new Color(128, 0, 0); -	static final private Color mag_y_color = new Color(0, 128, 0); -	static final private Color mag_z_color = new Color(0, 0, 128); +	static final private Color accel_along_color = new Color(255, 0, 0); +	static final private Color accel_across_color = new Color(0, 255, 0); +	static final private Color accel_through_color = new Color(0, 0, 255); +	static final private Color gyro_roll_color = new Color(192, 0, 0); +	static final private Color gyro_pitch_color = new Color(0, 192, 0); +	static final private Color gyro_yaw_color = new Color(0, 0, 192); +	static final private Color mag_along_color = new Color(128, 0, 0); +	static final private Color mag_across_color = new Color(0, 128, 0); +	static final private Color mag_through_color = new Color(0, 0, 128);  	static final private Color orient_color = new Color(31, 31, 31); -	static AltosVoltage voltage_units = new AltosVoltage(); -	static AltosPressure pressure_units = new AltosPressure(); -	static AltosNsat nsat_units = new AltosNsat(); -	static AltosDbm dbm_units = new AltosDbm(); -	static AltosGyroUnits gyro_units = new AltosGyroUnits(); -	static AltosOrient orient_units = new AltosOrient(); -	static AltosMagUnits mag_units = new AltosMagUnits(); -	static AltosDopUnits dop_units = new AltosDopUnits(); +	static AltosUnits dop_units = null; + +	AltosUIFlightSeries flight_series; -	AltosUIAxis	height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis; -	AltosUIAxis	distance_axis, pressure_axis; -	AltosUIAxis	gyro_axis, orient_axis, mag_axis; -	AltosUIAxis	course_axis, dop_axis; +	AltosUITimeSeries[] setup(AltosFlightStats stats, AltosUIFlightSeries flight_series) { +		AltosCalData	cal_data = flight_series.cal_data(); -	public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosGraphDataSet dataSet) { -		super(enable); +		AltosUIAxis	height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis; +		AltosUIAxis	distance_axis, pressure_axis, thrust_axis; +		AltosUIAxis	gyro_axis, orient_axis, mag_axis; +		AltosUIAxis	course_axis, dop_axis; + +		if (stats.serial != AltosLib.MISSING && stats.product != null && stats.flight != AltosLib.MISSING) +			setName(String.format("%s %d flight %d\n", stats.product, stats.serial, stats.flight));  		height_axis = newAxis("Height", AltosConvert.height, height_color); -		pressure_axis = newAxis("Pressure", pressure_units, pressure_color, 0); +		pressure_axis = newAxis("Pressure", AltosConvert.pressure, pressure_color, 0);  		speed_axis = newAxis("Speed", AltosConvert.speed, speed_color); +		thrust_axis = newAxis("Thrust", AltosConvert.force, thrust_color);  		accel_axis = newAxis("Acceleration", AltosConvert.accel, accel_color); -		voltage_axis = newAxis("Voltage", voltage_units, voltage_color); +		voltage_axis = newAxis("Voltage", AltosConvert.voltage, voltage_color);  		temperature_axis = newAxis("Temperature", AltosConvert.temperature, temperature_color, 0); -		nsat_axis = newAxis("Satellites", nsat_units, gps_nsat_color, +		nsat_axis = newAxis("Satellites", null, gps_nsat_color,  				    AltosUIAxis.axis_include_zero | AltosUIAxis.axis_integer); -		dbm_axis = newAxis("Signal Strength", dbm_units, dbm_color, 0); +		dbm_axis = newAxis("Signal Strength", null, dbm_color, 0);  		distance_axis = newAxis("Distance", AltosConvert.distance, range_color); -		gyro_axis = newAxis("Rotation Rate", gyro_units, gyro_z_color, 0); -		orient_axis = newAxis("Tilt Angle", orient_units, orient_color, 0); -		mag_axis = newAxis("Magnetic Field", mag_units, mag_x_color, 0); -		course_axis = newAxis("Course", orient_units, gps_course_color, 0); +		gyro_axis = newAxis("Rotation Rate", AltosConvert.rotation_rate, gyro_roll_color, 0); +		orient_axis = newAxis("Tilt Angle", AltosConvert.orient, orient_color, 0); +		mag_axis = newAxis("Magnetic Field", AltosConvert.magnetic_field, mag_along_color, 0); +		course_axis = newAxis("Course", AltosConvert.orient, gps_course_color, 0);  		dop_axis = newAxis("Dilution of Precision", dop_units, gps_pdop_color, 0); -		addMarker("State", AltosGraphDataPoint.data_state, state_color); - -		if (stats.has_flight_data) { -			addSeries("Height", -				  AltosGraphDataPoint.data_height, -				  AltosConvert.height, -				  height_color, -				  true, -				  height_axis); -			addSeries("Pressure", -				  AltosGraphDataPoint.data_pressure, -				  pressure_units, -				  pressure_color, -				  false, -				  pressure_axis); -			addSeries("Speed", -				  AltosGraphDataPoint.data_speed, -				  AltosConvert.speed, -				  speed_color, -				  true, -				  speed_axis); -			addSeries("Acceleration", -				  AltosGraphDataPoint.data_accel, -				  AltosConvert.accel, -				  accel_color, -				  true, -				  accel_axis); -		} -		if (stats.has_gps) { -			boolean	enable_gps = false; - -			if (!stats.has_flight_data) -				enable_gps = true; - -			addSeries("Range", -				  AltosGraphDataPoint.data_range, -				  AltosConvert.distance, -				  range_color, -				  false, -				  distance_axis); -			addSeries("Distance", -				  AltosGraphDataPoint.data_distance, -				  AltosConvert.distance, -				  distance_color, -				  enable_gps, -				  distance_axis); -			addSeries("GPS Height", -				  AltosGraphDataPoint.data_gps_height, -				  AltosConvert.height, -				  gps_height_color, -				  enable_gps, -				  height_axis); -			addSeries("GPS Altitude", -				  AltosGraphDataPoint.data_gps_altitude, -				  AltosConvert.height, -				  gps_height_color, -				  false, -				  height_axis); -			addSeries("GPS Satellites in Solution", -				  AltosGraphDataPoint.data_gps_nsat_solution, -				  nsat_units, -				  gps_nsat_solution_color, -				  false, -				  nsat_axis); -			if (stats.has_gps_sats) { -				addSeries("GPS Satellites in View", -					  AltosGraphDataPoint.data_gps_nsat_view, -					  nsat_units, -					  gps_nsat_view_color, -					  false, -					  nsat_axis); -			} -			if (stats.has_gps_detail) { -				addSeries("GPS Course", -					  AltosGraphDataPoint.data_gps_course, -					  orient_units, -					  gps_course_color, -					  false, -					  course_axis); -				addSeries("GPS Ground Speed", -					  AltosGraphDataPoint.data_gps_ground_speed, -					  AltosConvert.speed, -					  gps_ground_speed_color, -					  enable_gps, -					  speed_axis); -				addSeries("GPS Climb Rate", -					  AltosGraphDataPoint.data_gps_climb_rate, -					  AltosConvert.speed, -					  gps_climb_rate_color, -					  enable_gps, -					  speed_axis); -			} -			addSeries("GPS Position DOP", -				  AltosGraphDataPoint.data_gps_pdop, -				  dop_units, -				  gps_pdop_color, -				  false, -				  dop_axis); -			if (stats.has_gps_detail) { -				addSeries("GPS Horizontal DOP", -					  AltosGraphDataPoint.data_gps_hdop, -					  dop_units, -					  gps_hdop_color, -					  false, -					  dop_axis); -				addSeries("GPS Vertical DOP", -					  AltosGraphDataPoint.data_gps_vdop, -					  dop_units, -					  gps_vdop_color, -					  false, -					  dop_axis); -			} -		} -		if (stats.has_rssi) -			addSeries("Received Signal Strength", -				  AltosGraphDataPoint.data_rssi, -				  dbm_units, -				  dbm_color, -				  false, -				  dbm_axis); - -		if (stats.has_battery) -			addSeries("Battery Voltage", -				  AltosGraphDataPoint.data_battery_voltage, -				  voltage_units, -				  battery_voltage_color, -				  false, -				  voltage_axis); - -		if (stats.has_flight_adc) { -			addSeries("Temperature", -				  AltosGraphDataPoint.data_temperature, -				  AltosConvert.temperature, -				  temperature_color, -				  false, -				  temperature_axis); -			addSeries("Drogue Voltage", -				  AltosGraphDataPoint.data_drogue_voltage, -				  voltage_units, -				  drogue_voltage_color, -				  false, -				  voltage_axis); -			addSeries("Main Voltage", -				  AltosGraphDataPoint.data_main_voltage, -				  voltage_units, -				  main_voltage_color, -				  false, -				  voltage_axis); +		flight_series.register_axis("default", +					    speed_color, +					    false, +					    speed_axis); + +		flight_series.register_marker(AltosUIFlightSeries.state_name, +					      state_color, +					      true, +					      plot, +					      true); + +		flight_series.register_marker(AltosUIFlightSeries.pyro_fired_name, +					      igniter_marker_color, +					      true, +					      plot, +					      false); + +		flight_series.register_axis(AltosUIFlightSeries.accel_name, +					    accel_color, +					    true, +					    accel_axis); + +		flight_series.register_axis(AltosUIFlightSeries.vert_accel_name, +					    vert_accel_color, +					    true, +					    accel_axis); + +		flight_series.register_axis(AltosUIFlightSeries.kalman_accel_name, +					    kalman_accel_color, +					    false, +					    accel_axis); + +		flight_series.register_axis(AltosUIFlightSeries.rssi_name, +					    dbm_color, +					    false, +					    dbm_axis); + +		flight_series.register_axis(AltosUIFlightSeries.speed_name, +					    speed_color, +					    true, +					    speed_axis); + +		flight_series.register_axis(AltosUIFlightSeries.kalman_speed_name, +					    kalman_speed_color, +					    true, +					    speed_axis); + +		flight_series.register_axis(AltosUIFlightSeries.pressure_name, +					    pressure_color, +					    false, +					    pressure_axis); + +		flight_series.register_axis(AltosUIFlightSeries.height_name, +					    height_color, +					    true, +					    height_axis); + +		flight_series.register_axis(AltosUIFlightSeries.altitude_name, +					    height_color, +					    false, +					    height_axis); + +		flight_series.register_axis(AltosUIFlightSeries.kalman_height_name, +					    kalman_height_color, +					    false, +					    height_axis); + + +		flight_series.register_axis(AltosUIFlightSeries.temperature_name, +					    temperature_color, +					    false, +					    temperature_axis); + +		flight_series.register_axis(AltosUIFlightSeries.battery_voltage_name, +					    battery_voltage_color, +					    false, +					    voltage_axis); + +		flight_series.register_axis(AltosUIFlightSeries.apogee_voltage_name, +					    drogue_voltage_color, +					    false, +					    voltage_axis); + +		flight_series.register_axis(AltosUIFlightSeries.main_voltage_name, +					    main_voltage_color, +					    false, +					    voltage_axis); + +		flight_series.register_axis(AltosUIFlightSeries.sats_in_view_name, +					    gps_nsat_view_color, +					    false, +					    nsat_axis); + +		flight_series.register_axis(AltosUIFlightSeries.sats_in_soln_name, +					    gps_nsat_solution_color, +					    false, +					    nsat_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gps_pdop_name, +					    gps_pdop_color, +					    false, +					    dop_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gps_hdop_name, +					    gps_hdop_color, +					    false, +					    dop_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gps_vdop_name, +					    gps_vdop_color, +					    false, +					    dop_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gps_altitude_name, +					    gps_height_color, +					    false, +					    height_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gps_height_name, +					    gps_height_color, +					    false, +					    height_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gps_ground_speed_name, +					    gps_ground_speed_color, +					    false, +					    speed_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gps_ascent_rate_name, +					    gps_climb_rate_color, +					    false, +					    speed_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gps_course_name, +					    gps_course_color, +					    false, +					    course_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gps_speed_name, +					    gps_speed_color, +					    false, +					    speed_axis); + +		flight_series.register_axis(AltosUIFlightSeries.accel_along_name, +					    accel_along_color, +					    false, +					    accel_axis); + +		flight_series.register_axis(AltosUIFlightSeries.accel_across_name, +					    accel_across_color, +					    false, +					    accel_axis); + +		flight_series.register_axis(AltosUIFlightSeries.accel_through_name, +					    accel_through_color, +					    false, +					    accel_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gyro_roll_name, +					    gyro_roll_color, +					    false, +					    gyro_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gyro_pitch_name, +					    gyro_pitch_color, +					    false, +					    gyro_axis); + +		flight_series.register_axis(AltosUIFlightSeries.gyro_yaw_name, +					    gyro_yaw_color, +					    false, +					    gyro_axis); + +		flight_series.register_axis(AltosUIFlightSeries.mag_along_name, +					    mag_along_color, +					    false, +					    mag_axis); + +		flight_series.register_axis(AltosUIFlightSeries.mag_across_name, +					    mag_across_color, +					    false, +					    mag_axis); + +		flight_series.register_axis(AltosUIFlightSeries.mag_through_name, +					    mag_through_color, +					    false, +					    mag_axis); + +		flight_series.register_axis(AltosUIFlightSeries.orient_name, +					    orient_color, +					    false, +					    orient_axis); + +		for (int channel = 0; channel < 26; channel++) { +			flight_series.register_axis(flight_series.igniter_voltage_name(channel), +						    igniter_voltage_color, +						    false, +						    voltage_axis);  		} -		if (stats.has_imu) { -			addSeries("Acceleration Along", -				  AltosGraphDataPoint.data_accel_along, -				  AltosConvert.accel, -				  accel_x_color, -				  false, -				  accel_axis); -			addSeries("Acceleration Across", -				  AltosGraphDataPoint.data_accel_across, -				  AltosConvert.accel, -				  accel_y_color, -				  false, -				  accel_axis); -			addSeries("Acceleration Through", -				  AltosGraphDataPoint.data_accel_through, -				  AltosConvert.accel, -				  accel_z_color, -				  false, -				  accel_axis); -			addSeries("Roll Rate", -				  AltosGraphDataPoint.data_gyro_roll, -				  gyro_units, -				  gyro_x_color, -				  false, -				  gyro_axis); -			addSeries("Pitch Rate", -				  AltosGraphDataPoint.data_gyro_pitch, -				  gyro_units, -				  gyro_y_color, -				  false, -				  gyro_axis); -			addSeries("Yaw Rate", -				  AltosGraphDataPoint.data_gyro_yaw, -				  gyro_units, -				  gyro_z_color, -				  false, -				  gyro_axis); -		} -		if (stats.has_mag) { -			addSeries("Magnetometer Along", -				  AltosGraphDataPoint.data_mag_along, -				  mag_units, -				  mag_x_color, -				  false, -				  mag_axis); -			addSeries("Magnetometer Across", -				  AltosGraphDataPoint.data_mag_across, -				  mag_units, -				  mag_y_color, -				  false, -				  mag_axis); -			addSeries("Magnetometer Through", -				  AltosGraphDataPoint.data_mag_through, -				  mag_units, -				  mag_z_color, -				  false, -				  mag_axis); -		} -		if (stats.has_orient) -			addSeries("Tilt Angle", -				  AltosGraphDataPoint.data_orient, -				  orient_units, -				  orient_color, -				  false, -				  orient_axis); -		if (stats.num_ignitor > 0) { -			for (int i = 0; i < stats.num_ignitor; i++) -				addSeries(AltosLib.ignitor_name(i), -					  AltosGraphDataPoint.data_ignitor_0 + i, -					  voltage_units, -					  main_voltage_color, -					  false, -					  voltage_axis); -			for (int i = 0; i < stats.num_ignitor; i++) -				addMarker(AltosLib.ignitor_name(i), AltosGraphDataPoint.data_ignitor_fired_0 + i, state_color); -		} +		flight_series.register_axis(AltosUIFlightSeries.thrust_name, +					    thrust_color, +					    true, +					    thrust_axis); + +		return flight_series.series(cal_data); +	} + +	public void set_data(AltosFlightStats stats, AltosUIFlightSeries flight_series) { +		set_series(setup(stats, flight_series)); +	} + +	public AltosGraph(AltosUIEnable enable) { +		super(enable, "Flight"); +	} -		setDataSet(dataSet); +	public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosUIFlightSeries flight_series) { +		this(enable); +		set_series(setup(stats, flight_series));  	}  } diff --git a/altosuilib/AltosGraphDataPoint.java b/altosuilib/AltosGraphDataPoint.java deleted file mode 100644 index 0012d96a..00000000 --- a/altosuilib/AltosGraphDataPoint.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright © 2013 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_11; - -import org.altusmetrum.altoslib_11.*; - -public class AltosGraphDataPoint implements AltosUIDataPoint { - -	AltosState	state; - -	public static final int data_height = 0; -	public static final int data_speed = 1; -	public static final int data_accel = 2; -	public static final int data_temp = 3; -	public static final int data_battery_voltage = 4; -	public static final int data_drogue_voltage = 5; -	public static final int data_main_voltage = 6; -	public static final int data_rssi = 7; -	public static final int data_state = 8; -	public static final int data_gps_height = 9; -	public static final int data_gps_nsat_solution = 10; -	public static final int data_gps_nsat_view = 11; -	public static final int data_gps_altitude = 12; -	public static final int data_temperature = 13; -	public static final int data_range = 14; -	public static final int data_distance = 15; -	public static final int data_pressure = 16; -	public static final int data_accel_along = 17; -	public static final int data_accel_across = 18; -	public static final int data_accel_through = 19; -	public static final int data_gyro_roll = 20; -	public static final int data_gyro_pitch = 21; -	public static final int data_gyro_yaw = 22; -	public static final int data_mag_along = 23; -	public static final int data_mag_across = 24; -	public static final int data_mag_through = 25; -	public static final int data_orient = 26; -	public static final int data_gps_course = 27; -	public static final int data_gps_ground_speed = 28; -	public static final int data_gps_climb_rate = 29; -	public static final int data_gps_pdop = 30; -	public static final int data_gps_hdop = 31; -	public static final int data_gps_vdop = 32; -	public static final int data_ignitor_0 = 33; -	public static final int data_ignitor_num = 32; -	public static final int data_ignitor_max = data_ignitor_0 + data_ignitor_num - 1; -	public static final int data_ignitor_fired_0 = data_ignitor_0 + data_ignitor_num; -	public static final int data_ignitor_fired_max = data_ignitor_fired_0 + data_ignitor_num - 1; - -	public double x() throws AltosUIDataMissing { -		double	time = state.time_since_boost(); -		if (time < -2) -			throw new AltosUIDataMissing(-1); -		return time; -	} - -	public double y(int index) throws AltosUIDataMissing { -		double y = AltosLib.MISSING; -		switch (index) { -		case data_height: -			y = state.height(); -			break; -		case data_speed: -			y = state.speed(); -			break; -		case data_accel: -			y = state.acceleration(); -			break; -		case data_temp: -			y = state.temperature; -			break; -		case data_battery_voltage: -			y = state.battery_voltage; -			break; -		case data_drogue_voltage: -			y = state.apogee_voltage; -			break; -		case data_main_voltage: -			y = state.main_voltage; -			break; -		case data_rssi: -			y = state.rssi; -			break; -		case data_gps_height: -			y = state.gps_height; -			break; -		case data_gps_nsat_solution: -			if (state.gps != null) -				y = state.gps.nsat; -			break; -		case data_gps_nsat_view: -			if (state.gps != null) { -				if (state.gps.cc_gps_sat != null) -					y = state.gps.cc_gps_sat.length; -				else -					y = 0; -			} -			break; -		case data_gps_altitude: -			y = state.gps_altitude(); -			break; -		case data_temperature: -			y = state.temperature; -			break; -		case data_range: -			y = state.range; -			break; -		case data_distance: -			if (state.from_pad != null) -				y = state.from_pad.distance; -			break; -		case data_pressure: -			y = state.pressure(); -			break; - -		case data_accel_along: -			y = state.accel_along(); -			break; -		case data_accel_across: -			y = state.accel_across(); -			break; -		case data_accel_through: -			y = state.accel_through(); -			break; -		case data_gyro_roll: -			y = state.gyro_roll(); -			break; -		case data_gyro_pitch: -			y = state.gyro_pitch(); -			break; -		case data_gyro_yaw: -			y = state.gyro_yaw(); -			break; -		case data_mag_along: -			y = state.mag_along(); -			break; -		case data_mag_across: -			y = state.mag_across(); -			break; -		case data_mag_through: -			y = state.mag_through(); -			break; -		case data_orient: -			y = state.orient(); -			break; -		case data_gps_course: -			if (state.gps != null) -				y = state.gps.course; -			else -				y = AltosLib.MISSING; -			break; -		case data_gps_ground_speed: -			if (state.gps != null) -				y = state.gps.ground_speed; -			else -				y = AltosLib.MISSING; -			break; -		case data_gps_climb_rate: -			if (state.gps != null) -				y = state.gps.climb_rate; -			else -				y = AltosLib.MISSING; -			break; -		case data_gps_pdop: -			if (state.gps != null) -				y = state.gps.pdop; -			else -				y = AltosLib.MISSING; -			break; -		case data_gps_hdop: -			if (state.gps != null) -				y = state.gps.hdop; -			else -				y = AltosLib.MISSING; -			break; -		case data_gps_vdop: -			if (state.gps != null) -				y = state.gps.vdop; -			else -				y = AltosLib.MISSING; -			break; -		default: -			if (data_ignitor_0 <= index && index <= data_ignitor_max) { -				int ignitor = index - data_ignitor_0; -				if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) -					y = state.ignitor_voltage[ignitor]; -			} else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { -				int ignitor = index - data_ignitor_fired_0; -				if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { -					if ((state.pyro_fired & (1 << ignitor)) != 0) -						y = 1; -					else -						y = 0; -				} -			} -			break; -		} -		if (y == AltosLib.MISSING) -			throw new AltosUIDataMissing(index); -		return y; -	} - -	public int id(int index) { -		if (index == data_state) { -			int s = state.state(); -			if (AltosLib.ao_flight_boost <= s && s <= AltosLib.ao_flight_landed) -				return s; -		} else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { -			int ignitor = index - data_ignitor_fired_0; -			if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { -				if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { -					if ((state.pyro_fired & (1 << ignitor)) != 0) -						return 1; -				} -			} -		} -		return -1; -	} - -	public String id_name(int index) { -		if (index == data_state) { -			return state.state_name(); -		} else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { -			int ignitor = index - data_ignitor_fired_0; -			if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) -				return AltosLib.ignitor_name(ignitor); -		} -		return ""; -	} - -	public AltosGraphDataPoint (AltosState state) { -		this.state = state; -	} -} diff --git a/altosuilib/AltosGraphDataSet.java b/altosuilib/AltosGraphDataSet.java deleted file mode 100644 index 065a7815..00000000 --- a/altosuilib/AltosGraphDataSet.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2013 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_11; - -import java.lang.*; -import java.io.*; -import java.util.*; -import org.altusmetrum.altoslib_11.*; - -class AltosGraphIterator implements Iterator<AltosUIDataPoint> { -	AltosGraphDataSet	dataSet; -	Iterator<AltosState>	iterator; - -	public boolean hasNext() { -		return iterator.hasNext(); -	} - -	public AltosUIDataPoint next() { -		AltosState	state = iterator.next(); - -		if (state.flight != AltosLib.MISSING) { -			if (dataSet.callsign == null && state.callsign != null) -				dataSet.callsign = state.callsign; - -			if (dataSet.serial == 0 && state.serial != 0) -				dataSet.serial = state.serial; - -			if (dataSet.flight == 0 && state.flight != 0) -				dataSet.flight = state.flight; -		} - -		return new AltosGraphDataPoint(state); -	} - -	public AltosGraphIterator (Iterator<AltosState> iterator, AltosGraphDataSet dataSet) { -		this.iterator = iterator; -		this.dataSet = dataSet; -	} - -	public void remove() { -	} -} - -class AltosGraphIterable implements Iterable<AltosUIDataPoint> { -	AltosGraphDataSet	dataSet; - -	public Iterator<AltosUIDataPoint> iterator() { -		return new AltosGraphIterator(dataSet.states.iterator(), dataSet); -	} - -	public AltosGraphIterable(AltosGraphDataSet dataSet) { -		this.dataSet = dataSet; -	} -} - -public class AltosGraphDataSet implements AltosUIDataSet { -	String			callsign; -	int			serial; -	int			flight; -	AltosStateIterable	states; - -	public String name() { -		if (callsign != null) -			return String.format("%s - %d/%d", callsign, serial, flight); -		else -			return String.format("%d/%d", serial, flight); -	} - -	public Iterable<AltosUIDataPoint> dataPoints() { -		return new AltosGraphIterable(this); -	} - -	public AltosGraphDataSet (AltosStateIterable states) { -		this.states = states; -		this.callsign = null; -		this.serial = 0; -		this.flight = 0; -	} -} diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java index 7ede2824..9e528b1f 100644 --- a/altosuilib/AltosInfoTable.java +++ b/altosuilib/AltosInfoTable.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*;  import javax.swing.table.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {  	private AltosFlightInfoTableModel model; @@ -128,6 +128,8 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar  	public void show(AltosState state, AltosListenerState listener_state) { +		AltosCalData	cal_data = state.cal_data(); +  		if (!isShowing()) {  			last_state = state;  			last_listener_state = listener_state; @@ -136,14 +138,14 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar  		reset();  		if (state != null) { -			if (state.device_type != AltosLib.MISSING) -				info_add_row(0, "Device", "%s", AltosLib.product_name(state.device_type)); -			else if (state.product != null) -				info_add_row(0, "Device", "%s", state.product); +			if (cal_data.device_type != AltosLib.MISSING) +				info_add_row(0, "Device", "%s", AltosLib.product_name(cal_data.device_type)); +			else if (cal_data.product != null) +				info_add_row(0, "Device", "%s", cal_data.product);  			if (state.altitude() != AltosLib.MISSING)  				info_add_row(0, "Altitude", "%6.0f    m", state.altitude()); -			if (state.ground_altitude() != AltosLib.MISSING) -				info_add_row(0, "Pad altitude", "%6.0f    m", state.ground_altitude()); +			if (cal_data.ground_altitude != AltosLib.MISSING) +				info_add_row(0, "Pad altitude", "%6.0f    m", cal_data.ground_altitude);  			if (state.height() != AltosLib.MISSING)  				info_add_row(0, "Height", "%6.0f    m", state.height());  			if (state.max_height() != AltosLib.MISSING) diff --git a/altosuilib/AltosLed.java b/altosuilib/AltosLed.java index c06e45e5..b53e7604 100644 --- a/altosuilib/AltosLed.java +++ b/altosuilib/AltosLed.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import javax.swing.*; diff --git a/altosuilib/AltosLights.java b/altosuilib/AltosLights.java index 394cfc67..7b02d770 100644 --- a/altosuilib/AltosLights.java +++ b/altosuilib/AltosLights.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import javax.swing.*; diff --git a/altosuilib/AltosPositionListener.java b/altosuilib/AltosPositionListener.java index 8c4d2516..f44735e2 100644 --- a/altosuilib/AltosPositionListener.java +++ b/altosuilib/AltosPositionListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  public interface AltosPositionListener {  	public void position_changed(int position); diff --git a/altosuilib/AltosRomconfigUI.java b/altosuilib/AltosRomconfigUI.java index c1b8ac26..74323218 100644 --- a/altosuilib/AltosRomconfigUI.java +++ b/altosuilib/AltosRomconfigUI.java @@ -16,12 +16,12 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosRomconfigUI  	extends AltosUIDialog diff --git a/altosuilib/AltosScanUI.java b/altosuilib/AltosScanUI.java index 8843429a..c63f027c 100644 --- a/altosuilib/AltosScanUI.java +++ b/altosuilib/AltosScanUI.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*; @@ -26,7 +26,7 @@ import java.io.*;  import java.util.*;  import java.text.*;  import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  class AltosScanResult {  	String		callsign; @@ -213,10 +213,11 @@ public class AltosScanUI  						if (state == null)  							continue;  						packet_count++; -						if (state.flight != AltosLib.MISSING) { -							final AltosScanResult	result = new AltosScanResult(state.callsign, -													     state.serial, -													     state.flight, +						AltosCalData	cal_data = state.cal_data(); +						if (cal_data.flight != AltosLib.MISSING) { +							final AltosScanResult	result = new AltosScanResult(cal_data.callsign, +													     cal_data.serial, +													     cal_data.flight,  													     frequencies[frequency_index],  													     telemetry,  													     rate); diff --git a/altosuilib/AltosSerial.java b/altosuilib/AltosSerial.java index 5c32a7d8..d7c6129c 100644 --- a/altosuilib/AltosSerial.java +++ b/altosuilib/AltosSerial.java @@ -20,13 +20,13 @@   * Deal with TeleDongle on a serial port   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.io.*;  import java.util.*;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import libaltosJNI.*;  /* diff --git a/altosuilib/AltosSerialInUseException.java b/altosuilib/AltosSerialInUseException.java index e0de8ad7..c8ca4d56 100644 --- a/altosuilib/AltosSerialInUseException.java +++ b/altosuilib/AltosSerialInUseException.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  public class AltosSerialInUseException extends Exception {  	public AltosDevice	device; diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java index e41667ef..fe94f161 100644 --- a/altosuilib/AltosUIAxis.java +++ b/altosuilib/AltosUIAxis.java @@ -16,14 +16,14 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.io.*;  import java.util.ArrayList;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import org.jfree.ui.*;  import org.jfree.chart.*; @@ -49,11 +49,14 @@ public class AltosUIAxis extends NumberAxis {  	public final static int axis_default = axis_include_zero;  	public void set_units() { -		String u = units.parse_units(); -		if (u != null) -			setLabel(String.format("%s (%s)", label, u)); -		else -			setLabel(label); +		if (units != null) { +			String u = units.parse_units(); +			if (u != null) { +				setLabel(String.format("%s (%s)", label, u)); +				return; +			} +		} +		setLabel(label);  	}  	public void set_enable(boolean enable) { diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java index 19512f49..e3d86724 100644 --- a/altosuilib/AltosUIConfigure.java +++ b/altosuilib/AltosUIConfigure.java @@ -16,14 +16,14 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*;  import java.beans.*;  import javax.swing.*;  import javax.swing.event.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  class DelegatingRenderer implements ListCellRenderer<Object> { diff --git a/altosuilib/AltosUIDataMissing.java b/altosuilib/AltosUIDataMissing.java index a59cc0a0..05227e1d 100644 --- a/altosuilib/AltosUIDataMissing.java +++ b/altosuilib/AltosUIDataMissing.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  public class AltosUIDataMissing extends Exception {  	public int	id; diff --git a/altosuilib/AltosUIDataPoint.java b/altosuilib/AltosUIDataPoint.java index 4107feae..36fadeaf 100644 --- a/altosuilib/AltosUIDataPoint.java +++ b/altosuilib/AltosUIDataPoint.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  public interface AltosUIDataPoint {  	public abstract double x() throws AltosUIDataMissing; diff --git a/altosuilib/AltosUIDataSet.java b/altosuilib/AltosUIDataSet.java index ffab46c1..ddda3d3d 100644 --- a/altosuilib/AltosUIDataSet.java +++ b/altosuilib/AltosUIDataSet.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  public interface AltosUIDataSet {  	public abstract String name(); diff --git a/altosuilib/AltosUIDialog.java b/altosuilib/AltosUIDialog.java index 85b40229..5eafa457 100644 --- a/altosuilib/AltosUIDialog.java +++ b/altosuilib/AltosUIDialog.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*; diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java index 4c733b96..0c23fa8d 100644 --- a/altosuilib/AltosUIEnable.java +++ b/altosuilib/AltosUIEnable.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*; @@ -24,7 +24,7 @@ import javax.swing.*;  import java.io.*;  import java.util.concurrent.*;  import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import org.jfree.ui.*;  import org.jfree.chart.*; diff --git a/altosuilib/AltosUIFlightSeries.java b/altosuilib/AltosUIFlightSeries.java new file mode 100644 index 00000000..19bed609 --- /dev/null +++ b/altosuilib/AltosUIFlightSeries.java @@ -0,0 +1,124 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altosuilib_12; + +import java.util.*; +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_12.*; + +import org.jfree.ui.*; +import org.jfree.chart.*; +import org.jfree.chart.plot.*; +import org.jfree.chart.axis.*; +import org.jfree.chart.renderer.*; +import org.jfree.chart.renderer.xy.*; +import org.jfree.chart.labels.*; +import org.jfree.data.xy.*; +import org.jfree.data.*; + +class AltosUITimeSeriesAxis { +	Color		color; +	boolean		enabled; +	boolean		marker; +	boolean		marker_top; +	AltosUIAxis	axis; +	XYPlot		plot; + +	public AltosUITimeSeriesAxis(Color color, boolean enabled, AltosUIAxis axis, XYPlot plot, boolean marker, boolean marker_top) { +		this.color = color; +		this.enabled = enabled; +		this.axis = axis; +		this.plot = plot; +		this.marker = marker; +		this.marker_top = marker_top; +	} +} + +public class AltosUIFlightSeries extends AltosFlightSeries { + +	Hashtable<String,AltosUITimeSeriesAxis> axes; + +	AltosUIFlightSeries flight_series; + +	void fill_axes(String label, AltosUITimeSeriesAxis axis) { +		for (AltosTimeSeries ts : series) { +			AltosUITimeSeries uts = (AltosUITimeSeries) ts; + +			if (label.equals(ts.label) || (label.equals("default") && uts.color == null)) { +				if (axis.marker) +					uts.set_marker(axis.color, axis.enabled, axis.plot, axis.marker_top); +				else +					uts.set_axis(axis.color, axis.enabled, axis.axis); +			} +		} +	} + +	public void register_axis(String label, +				  Color color, +				  boolean enabled, +				  AltosUIAxis axis) { +		AltosUITimeSeriesAxis tsa = new AltosUITimeSeriesAxis(color, +								      enabled, +								      axis, +								      null, +								      false, +								      false); +		axes.put(label, tsa); +		fill_axes(label, tsa); +	} + +	public void register_marker(String label, +				    Color color, +				    boolean enabled, +				    XYPlot plot, +				    boolean marker_top) { +		AltosUITimeSeriesAxis tsa = new AltosUITimeSeriesAxis(color, +								      enabled, +								      null, +								      plot, +								      true, +								      marker_top); +		axes.put(label, tsa); +		fill_axes(label, tsa); +	} + +	public AltosTimeSeries make_series(String label, AltosUnits units) { + + +		AltosUITimeSeries time_series = new AltosUITimeSeries(label, units); + +		AltosUITimeSeriesAxis tsa = axes.get(label); +		if (tsa == null) +			tsa = axes.get("default"); +		if (tsa != null) { +			if (tsa.marker) +				time_series.set_marker(tsa.color, tsa.enabled, tsa.plot, tsa.marker_top); +			else +				time_series.set_axis(tsa.color, tsa.enabled, tsa.axis); +		} +		return time_series; +	} + +	public AltosUITimeSeries[] series(AltosCalData cal_data) { +		finish(); +		return series.toArray(new AltosUITimeSeries[0]); +	} + +	public AltosUIFlightSeries (AltosCalData cal_data) { +		super(cal_data); +		axes = new Hashtable<String,AltosUITimeSeriesAxis>(); +	} +} diff --git a/altosuilib/AltosUIFlightTab.java b/altosuilib/AltosUIFlightTab.java index 3adbdb33..cf6a0c74 100644 --- a/altosuilib/AltosUIFlightTab.java +++ b/altosuilib/AltosUIFlightTab.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.util.*;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener {  	public GridBagLayout	layout; diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java index e5007fff..b7eee664 100644 --- a/altosuilib/AltosUIFrame.java +++ b/altosuilib/AltosUIFrame.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*; diff --git a/altosuilib/AltosUIFreqList.java b/altosuilib/AltosUIFreqList.java index 4dd9fece..7a5c3543 100644 --- a/altosuilib/AltosUIFreqList.java +++ b/altosuilib/AltosUIFreqList.java @@ -16,10 +16,10 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosUIFreqList extends JComboBox<AltosFrequency> { diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java index d3760384..0caabcfa 100644 --- a/altosuilib/AltosUIGraph.java +++ b/altosuilib/AltosUIGraph.java @@ -16,14 +16,15 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.io.*; +import java.util.*;  import java.util.ArrayList;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import org.jfree.ui.*;  import org.jfree.chart.*; @@ -42,10 +43,10 @@ public class AltosUIGraph implements AltosUnitsListener {  	public ChartPanel		panel;  	NumberAxis			xAxis;  	AltosUIEnable			enable; -	ArrayList<AltosUIGrapher>	graphers; -	AltosUIDataSet			dataSet; +	AltosUITimeSeries[]		series;  	int				axis_index;  	int				series_index; +	Hashtable<Integer,Boolean>	axes_added;  	static final private Color gridline_color = new Color(0, 0, 0);  	static final private Color border_color = new Color(255, 255, 255); @@ -65,70 +66,65 @@ public class AltosUIGraph implements AltosUnitsListener {  		return newAxis(label, units, color, AltosUIAxis.axis_default);  	} -	public void addSeries(String label, int fetch, AltosUnits units, Color color, -			      boolean enabled, AltosUIAxis axis) { -		AltosUISeries		series = new AltosUISeries(label, fetch, units, color, enabled, axis); -		XYSeriesCollection	dataset = new XYSeriesCollection(series); +	void addAxis(AltosUIAxis axis) { +		if (!axes_added.containsKey(axis.index)) { +			axes_added.put(axis.index, true); +			plot.setRangeAxis(axis.index, axis); +		} +	} + +	public void addSeries(AltosUITimeSeries series) { +		XYSeriesCollection	dataset = new XYSeriesCollection(series.xy_series()); + +		addAxis(series.axis);  		series.renderer.setPlot(plot);  		plot.setDataset(series_index, dataset);  		plot.setRenderer(series_index, series.renderer); -		plot.mapDatasetToRangeAxis(series_index, axis.index); +		plot.mapDatasetToRangeAxis(series_index, series.axis.index);  		if (enable != null) -			enable.add(label, series, enabled); -		this.graphers.add(series); +			enable.add(series.label, series, series.enable);  		series_index++;  	} -	public void addSeries(String label, int fetch, AltosUnits units, Color color) { -		addSeries(label, fetch, units, color, true, newAxis(label, units, color)); -	} - -	public void addMarker(String label, int fetch, Color color) { -		AltosUIMarker		marker = new AltosUIMarker(fetch, color, plot); -		this.graphers.add(marker); -	} - -	public void resetData() { -		for (AltosUIGrapher g : graphers) { -			g.clear(); -			g.setNotify(false); -		} -		if (dataSet != null) { -			for (AltosUIDataPoint dataPoint : dataSet.dataPoints()) -				for (AltosUIGrapher g : graphers) -					g.add(dataPoint); -		} -		for (AltosUIGrapher g : graphers) { -			g.setNotify(true); -			g.fireSeriesChanged(); -		} +	public void addMarker(AltosUITimeSeries series) {  	}  	public void units_changed(boolean imperial_units) { -		for (AltosUIGrapher g : graphers) -			g.set_units(); -		resetData(); +		for (AltosUITimeSeries s : series) +			s.set_units();  	}  	public void setName (String name) {  		chart.setTitle(name);  	} -	public void setDataSet (AltosUIDataSet dataSet) { -		this.dataSet = dataSet; -		resetData(); -		if (dataSet != null) -			setName(dataSet.name()); +	public void set_series(AltosUITimeSeries[] series) { +		this.series = series; +		boolean any_enabled = false; + +		for (AltosUITimeSeries s : series) +			if (s.enable) +				any_enabled = true; + +		if (!any_enabled) +			for (AltosUITimeSeries s : series) +				s.set_enable(true); + +		for (AltosUITimeSeries s : series) +			addSeries(s); + +		units_changed(false);  	} -	public AltosUIGraph(AltosUIEnable enable) { +	public AltosUIGraph(AltosUIEnable enable, String title) {  		this.enable = enable; -		this.graphers = new ArrayList<AltosUIGrapher>(); -		this.series_index = 0; +		this.series = null;  		this.axis_index = 0; +		axes_added = new Hashtable<Integer,Boolean>(); +  		xAxis = new NumberAxis("Time (s)");  		xAxis.setAutoRangeIncludesZero(true); @@ -139,7 +135,7 @@ public class AltosUIGraph implements AltosUnitsListener {  		plot.setDomainPannable(true);  		plot.setRangePannable(true); -		chart = new JFreeChart("Flight", JFreeChart.DEFAULT_TITLE_FONT, +		chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,  				       plot, true);  		ChartUtilities.applyCurrentTheme(chart); @@ -156,5 +152,6 @@ public class AltosUIGraph implements AltosUnitsListener {  		panel.setPreferredSize(new java.awt.Dimension(800, 500));  		AltosPreferences.register_units_listener(this); +  	}  } diff --git a/altosuilib/AltosUIGrapher.java b/altosuilib/AltosUIGrapher.java index 07358144..916d0b3f 100644 --- a/altosuilib/AltosUIGrapher.java +++ b/altosuilib/AltosUIGrapher.java @@ -16,14 +16,14 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.io.*;  import java.util.ArrayList;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import org.jfree.ui.*;  import org.jfree.chart.*; @@ -39,6 +39,8 @@ interface AltosUIGrapher {  	public abstract void set_units(); +	public abstract boolean need_reset(); +  	public abstract void clear();  	public abstract void add(AltosUIDataPoint dataPoint); diff --git a/altosuilib/AltosUIImage.java b/altosuilib/AltosUIImage.java index b157a2ce..f23b50bc 100644 --- a/altosuilib/AltosUIImage.java +++ b/altosuilib/AltosUIImage.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12;  import javax.swing.*;  import javax.imageio.ImageIO; diff --git a/altosuilib/AltosUIIndicator.java b/altosuilib/AltosUIIndicator.java index f47a2f29..ac2e6f06 100644 --- a/altosuilib/AltosUIIndicator.java +++ b/altosuilib/AltosUIIndicator.java @@ -16,11 +16,11 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {  	JLabel		label; diff --git a/altosuilib/AltosUILib.java b/altosuilib/AltosUILib.java index 0c5fa1c7..ef706e36 100644 --- a/altosuilib/AltosUILib.java +++ b/altosuilib/AltosUILib.java @@ -16,12 +16,12 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosUILib extends AltosLib { diff --git a/altosuilib/AltosUIListener.java b/altosuilib/AltosUIListener.java index 55ce584a..54a00661 100644 --- a/altosuilib/AltosUIListener.java +++ b/altosuilib/AltosUIListener.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  public interface AltosUIListener {  	public void ui_changed(String look_and_feel); diff --git a/altosuilib/AltosUIMap.java b/altosuilib/AltosUIMap.java index 3e4cbe9b..2e1e8f16 100644 --- a/altosuilib/AltosUIMap.java +++ b/altosuilib/AltosUIMap.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*; @@ -28,7 +28,7 @@ import java.awt.geom.*;  import java.util.*;  import java.util.concurrent.*;  import javax.imageio.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosMapInterface { @@ -413,6 +413,10 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM  		map.show(state, listener_state);  	} +	public void show(AltosGPS gps, int state) { +		map.show(gps, state); +	} +  	public String getName() {  		return "Map";  	} @@ -422,6 +426,10 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM  		map.centre(state);  	} +	public void centre(AltosGPS gps) { +		map.centre(gps); +	} +  	/* internal layout bits */  	private GridBagLayout layout = new GridBagLayout(); diff --git a/altosuilib/AltosUIMapPreload.java b/altosuilib/AltosUIMapPreload.java index 06c4c59b..81cda0d2 100644 --- a/altosuilib/AltosUIMapPreload.java +++ b/altosuilib/AltosUIMapPreload.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*; @@ -27,7 +27,7 @@ import java.text.*;  import java.lang.Math;  import java.net.URL;  import java.net.URLConnection; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  class AltosUIMapPos extends Box implements ActionListener {  	AltosUIMapPreload	preload; diff --git a/altosuilib/AltosUIMarker.java b/altosuilib/AltosUIMarker.java index 9d8dde60..90cdb291 100644 --- a/altosuilib/AltosUIMarker.java +++ b/altosuilib/AltosUIMarker.java @@ -16,14 +16,14 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.io.*;  import java.util.ArrayList;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import org.jfree.ui.*;  import org.jfree.chart.*; @@ -56,6 +56,8 @@ public class AltosUIMarker implements AltosUIGrapher {  	public void set_units() {  	} +	public boolean need_reset() { return true; } +  	public void set_enable(boolean enable) {  		if (enabled == enable)  			return; @@ -110,4 +112,4 @@ public class AltosUIMarker implements AltosUIGrapher {  	public AltosUIMarker (int fetch, Color color, XYPlot plot) {  		this(fetch, color, plot, true);  	} -}
\ No newline at end of file +} diff --git a/altosuilib/AltosUIPreferences.java b/altosuilib/AltosUIPreferences.java index c8ae9a7d..a2014065 100644 --- a/altosuilib/AltosUIPreferences.java +++ b/altosuilib/AltosUIPreferences.java @@ -16,13 +16,13 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.io.*;  import java.util.*;  import java.awt.Component;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosUIPreferences extends AltosPreferences { diff --git a/altosuilib/AltosUIPreferencesBackend.java b/altosuilib/AltosUIPreferencesBackend.java index 6dd2baaf..163ba173 100644 --- a/altosuilib/AltosUIPreferencesBackend.java +++ b/altosuilib/AltosUIPreferencesBackend.java @@ -16,11 +16,11 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.io.File;  import java.util.prefs.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  import javax.swing.filechooser.FileSystemView;  public class AltosUIPreferencesBackend extends AltosPreferencesBackend { diff --git a/altosuilib/AltosUIRateList.java b/altosuilib/AltosUIRateList.java index 187977d3..d1c15ce0 100644 --- a/altosuilib/AltosUIRateList.java +++ b/altosuilib/AltosUIRateList.java @@ -16,10 +16,10 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosUIRateList extends JComboBox<String> { @@ -27,10 +27,9 @@ public class AltosUIRateList extends JComboBox<String> {  	int	serial;  	public void set_rate(int new_rate) { -		int i; - -		setVisible(new_rate >= 0); -		setSelectedIndex(new_rate); +		if (new_rate != AltosLib.MISSING) +			setSelectedIndex(new_rate); +		setVisible(new_rate != AltosLib.MISSING);  	}  	public void set_product(String new_product) { diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java deleted file mode 100644 index 66cc7d69..00000000 --- a/altosuilib/AltosUISeries.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright © 2013 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_11; - -import java.io.*; -import java.util.ArrayList; - -import java.awt.*; -import javax.swing.*; -import org.altusmetrum.altoslib_11.*; - -import org.jfree.ui.*; -import org.jfree.chart.*; -import org.jfree.chart.plot.*; -import org.jfree.chart.axis.*; -import org.jfree.chart.renderer.*; -import org.jfree.chart.renderer.xy.*; -import org.jfree.chart.labels.*; -import org.jfree.data.xy.*; -import org.jfree.data.*; - -class AltosUITime extends AltosUnits { -	public double value(double v, boolean imperial_units) { return v; } - -	public double inverse(double v, boolean imperial_unis) { return v; } - -	public String show_units(boolean imperial_units) { return "s"; } - -	public String say_units(boolean imperial_units) { return "seconds"; } - -	public int show_fraction(int width, boolean imperial_units) { -		if (width < 5) -			return 0; -		return width - 5; -	} - -	public int say_fraction(boolean imperial_units) { return 0; } -} - -public class AltosUISeries extends XYSeries implements AltosUIGrapher { -	AltosUIAxis	axis; -	String		label; -	AltosUnits	units; -	Color		color; -	XYItemRenderer	renderer; -	int		fetch; -	boolean		enable; - -	public void set_units() { -		axis.set_units(); -		StandardXYToolTipGenerator	ttg; - -		String	time_example = (new AltosUITime()).graph_format(7); -		String  example = units.graph_format(7); - -		ttg = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", -								   units.graph_units()), -						     new java.text.DecimalFormat(time_example), -						     new java.text.DecimalFormat(example)); -		renderer.setBaseToolTipGenerator(ttg); -	} - -	public void set_enable(boolean enable) { -		if (this.enable != enable) { -			this.enable = enable; -			renderer.setSeriesVisible(0, enable); -			axis.set_enable(enable); -		} -	} - -	public void add(AltosUIDataPoint dataPoint) { -		try { -			super.add(dataPoint.x(), units.graph_value(dataPoint.y(fetch))); -		} catch (AltosUIDataMissing dm) { -		} -	} - -	public AltosUISeries (String label, int fetch, AltosUnits units, Color color, -			      boolean enable, AltosUIAxis axis) { -		super(label); -		this.label = label; -		this.fetch = fetch; -		this.units = units; -		this.color = color; -		this.enable = enable; -		this.axis = axis; - -		axis.ref(this.enable); - -		renderer = new XYLineAndShapeRenderer(true, false); -		renderer.setSeriesPaint(0, color); -		renderer.setSeriesStroke(0, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); -		renderer.setSeriesVisible(0, enable); -		set_units(); -	} -} diff --git a/altosuilib/AltosUITelemetryList.java b/altosuilib/AltosUITelemetryList.java index f02d2f7f..f884cd41 100644 --- a/altosuilib/AltosUITelemetryList.java +++ b/altosuilib/AltosUITelemetryList.java @@ -16,11 +16,11 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.util.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class AltosUITelemetryList extends JComboBox<String> { diff --git a/altosuilib/AltosUITimeSeries.java b/altosuilib/AltosUITimeSeries.java new file mode 100644 index 00000000..08f95ca7 --- /dev/null +++ b/altosuilib/AltosUITimeSeries.java @@ -0,0 +1,200 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_12; + +import java.io.*; +import java.util.ArrayList; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_12.*; + +import org.jfree.ui.*; +import org.jfree.chart.*; +import org.jfree.chart.plot.*; +import org.jfree.chart.axis.*; +import org.jfree.chart.renderer.*; +import org.jfree.chart.renderer.xy.*; +import org.jfree.chart.labels.*; +import org.jfree.data.xy.*; +import org.jfree.data.*; + +class AltosUITime extends AltosUnits { +	public double value(double v, boolean imperial_units) { return v; } + +	public double inverse(double v, boolean imperial_unis) { return v; } + +	public String show_units(boolean imperial_units) { return "s"; } + +	public String say_units(boolean imperial_units) { return "seconds"; } + +	public int show_fraction(int width, boolean imperial_units) { +		if (width < 5) +			return 0; +		return width - 5; +	} + +	public int say_fraction(boolean imperial_units) { return 0; } +} + +class AltosXYSeries extends XYSeries { + +	public AltosXYSeries(String label) { +		super(label); +	} +} + +public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher { +	Color		color; +	boolean		enable; +	AltosUIAxis	axis; +	boolean		marker; +	boolean		marker_top; +	XYItemRenderer	renderer; +	XYPlot		plot; +	AltosXYSeries	xy_series; +	ArrayList<ValueMarker>	markers; + + +	/* AltosUIGrapher interface */ +	public boolean need_reset() { +		return false; +	} + +	public void clear() { +	} + +	public void add(AltosUIDataPoint dataPoint) { +	} + +	public void setNotify(boolean notify) { +	} + +	public void fireSeriesChanged() { +	} + +	void set_data() { +		if (marker) { +			if (markers != null) { +				for (ValueMarker marker : markers) +					plot.removeDomainMarker(marker); +			} +			markers = new ArrayList<ValueMarker>(); +			for (AltosTimeValue v : this) { +				String s = units.string_value(v.value); +				ValueMarker marker = new ValueMarker(v.time); +				marker.setLabel(s); +				if (marker_top) { +					marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT); +					marker.setLabelTextAnchor(TextAnchor.TOP_LEFT); +				} else { +					marker.setLabelAnchor(RectangleAnchor.BOTTOM_RIGHT); +					marker.setLabelTextAnchor(TextAnchor.BOTTOM_LEFT); +				} +				marker.setPaint(color); +				if (enable) +					plot.addDomainMarker(marker); +				markers.add(marker); +			} +		} else { +			xy_series.clear(); + +			xy_series.setNotify(false); +			for (AltosTimeValue v : this) { +				double value = v.value; +				if (units != null) +					value = units.graph_value(value); +				xy_series.add(v.time, value); +			} +			xy_series.setNotify(true); +		} +	} + +	public void set_units() { +		axis.set_units(); +		StandardXYToolTipGenerator	ttg; + +		if (units != null) { +			String	time_example = (new AltosUITime()).graph_format(7); +			String  example = units.graph_format(7); + +			ttg = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", +									   units.graph_units()), +							     new java.text.DecimalFormat(time_example), +							     new java.text.DecimalFormat(example)); +			renderer.setBaseToolTipGenerator(ttg); +		} +		set_data(); +	} + +	public AltosXYSeries xy_series() { +		return xy_series; +	} + +	public void set_enable(boolean enable) { +		if (this.enable != enable) { +			this.enable = enable; +			if (marker) { +				for (ValueMarker marker : markers) { +					if (enable) +						plot.addDomainMarker(marker); +					else +						plot.removeDomainMarker(marker); +				} +			} else { +				renderer.setSeriesVisible(0, enable); +				axis.set_enable(enable); +			} +		} +	} + +	public void set_axis(Color color, boolean enable, AltosUIAxis axis) { +		this.color = color; +		this.enable = enable; +		this.axis = axis; +		this.marker = false; + +		axis.ref(this.enable); + +		renderer = new XYLineAndShapeRenderer(true, false); +		renderer.setSeriesPaint(0, color); +		renderer.setSeriesStroke(0, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); +		renderer.setSeriesVisible(0, enable); +		xy_series = new AltosXYSeries(label); +	} + +	public void set_marker(Color color, boolean enable, XYPlot plot, boolean marker_top) { +		this.color = color; +		this.enable = enable; +		this.marker = true; +		this.plot = plot; +		this.marker_top = marker_top; +	} + +	public AltosUITimeSeries(String label, AltosUnits units) { +		super(label, units); +	} + +	public AltosUITimeSeries(String label, AltosUnits units, +				 Color color, boolean enable, +				 AltosUIAxis axis) { +		this(label, units); +		set_axis(color, enable, axis); +	} +} diff --git a/altosuilib/AltosUIUnitsIndicator.java b/altosuilib/AltosUIUnitsIndicator.java index d4dd18db..bbfebef6 100644 --- a/altosuilib/AltosUIUnitsIndicator.java +++ b/altosuilib/AltosUIUnitsIndicator.java @@ -16,11 +16,11 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public abstract class AltosUIUnitsIndicator extends AltosUIIndicator { diff --git a/altosuilib/AltosUIVoltageIndicator.java b/altosuilib/AltosUIVoltageIndicator.java index 299c6114..297a6531 100644 --- a/altosuilib/AltosUIVoltageIndicator.java +++ b/altosuilib/AltosUIVoltageIndicator.java @@ -16,11 +16,11 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator { diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java index 221ac829..49f966f3 100644 --- a/altosuilib/AltosUSBDevice.java +++ b/altosuilib/AltosUSBDevice.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.util.*;  import libaltosJNI.*; diff --git a/altosuilib/AltosVoice.java b/altosuilib/AltosVoice.java index c651aa35..1d579a16 100644 --- a/altosuilib/AltosVoice.java +++ b/altosuilib/AltosVoice.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import com.sun.speech.freetts.Voice;  import com.sun.speech.freetts.VoiceManager; diff --git a/altosuilib/GrabNDrag.java b/altosuilib/GrabNDrag.java index 0e57fe4d..665ef89e 100644 --- a/altosuilib/GrabNDrag.java +++ b/altosuilib/GrabNDrag.java @@ -16,7 +16,7 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.awt.*;  import java.awt.event.*; diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index d18006b5..4b5eb524 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -18,7 +18,6 @@ altosuilib_JAVA = \  	AltosUIDataMissing.java \  	AltosUIDataPoint.java \  	AltosUIDataSet.java \ -	AltosUIGraph.java \  	AltosUIGrapher.java \  	AltosUIDialog.java \  	AltosUIEnable.java \ @@ -28,7 +27,9 @@ altosuilib_JAVA = \  	AltosUIMarker.java \  	AltosUIPreferencesBackend.java \  	AltosUIPreferences.java \ -	AltosUISeries.java \ +	AltosUIFlightSeries.java \ +	AltosUIGraph.java \ +	AltosGraph.java \  	AltosUSBDevice.java \  	AltosVoice.java \  	AltosDisplayThread.java \ @@ -50,9 +51,6 @@ altosuilib_JAVA = \  	AltosInfoTable.java \  	AltosFlightInfoTableModel.java \  	AltosFlightStatsTable.java \ -	AltosGraph.java \ -	AltosGraphDataPoint.java \ -	AltosGraphDataSet.java \  	AltosBTDevice.java \  	AltosBTDeviceIterator.java \  	AltosBTManage.java \ @@ -67,6 +65,7 @@ altosuilib_JAVA = \  	AltosUITelemetryList.java \  	AltosUIRateList.java \  	AltosUIImage.java \ +	AltosUITimeSeries.java \  	OSXAdapter.java  JAR=altosuilib_$(ALTOSUILIB_VERSION).jar diff --git a/altosuilib/OSXAdapter.java b/altosuilib/OSXAdapter.java index de5d5836..c338396f 100755 --- a/altosuilib/OSXAdapter.java +++ b/altosuilib/OSXAdapter.java @@ -55,7 +55,7 @@ Copyright © 2003-2007 Apple, Inc., All Rights Reserved  */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12;  import java.lang.reflect.*;  import java.util.HashMap; diff --git a/ao-bringup/.gitignore b/ao-bringup/.gitignore index dc7beb52..0cc15204 100644 --- a/ao-bringup/.gitignore +++ b/ao-bringup/.gitignore @@ -1,2 +1,3 @@  ao_led_blink  ao_radio_xmit +cal_values diff --git a/ao-bringup/test-easymini b/ao-bringup/test-easymini index e9948da9..7850b550 100755 --- a/ao-bringup/test-easymini +++ b/ao-bringup/test-easymini @@ -1,6 +1,6 @@  #!/bin/bash -VERSION=1.0 +VERSION=2.0  PRODUCT=EasyMini  BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'` diff --git a/ao-bringup/turnon_chaoskey b/ao-bringup/turnon_chaoskey index 990382f4..4a255bff 100755 --- a/ao-bringup/turnon_chaoskey +++ b/ao-bringup/turnon_chaoskey @@ -7,8 +7,8 @@ else      exit 1  fi -if [ -x /usr/bin/ao-usbload ]; then -	USBLOAD=/usr/bin/ao-usbload +if [ -x `which ao-usbload` ]; then +	USBLOAD=`which ao-usbload`  else  	echo "Can't find ao-usbload!  Aborting."  	exit 1 @@ -27,7 +27,7 @@ echo  FLASH_FILE=~/altusmetrumllc/Binaries/loaders/chaoskey-v1.0-altos-flash-*.bin  ALTOS_FILE=~/altusmetrumllc/Binaries/chaoskey-v1.0-*.elf -$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || exit 1 +$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || true  sleep 2 diff --git a/ao-bringup/turnon_easymini b/ao-bringup/turnon_easymini index 4580790a..9b66dc5e 100755 --- a/ao-bringup/turnon_easymini +++ b/ao-bringup/turnon_easymini @@ -1,12 +1,10 @@  #!/bin/sh -if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then -	FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc -elif [ -x /usr/bin/ao-flash-lpc ]; then -	FLASH_LPC=/usr/bin/ao-flash-lpc +if [ -x /usr/bin/dfu-util ]; then +    DFU_UTIL=/usr/bin/dfu-util  else -	echo "Can't find ao-flash-lpc!  Aborting." -	exit 1 +    echo "Can't find dfu-util! Aborting." +    exit 1  fi  if [ -x ../ao-tools/ao-usbload/ao-usbload ]; then @@ -18,17 +16,16 @@ else  	exit 1  fi -VERSION=1.0 +VERSION=2.0  PRODUCT=EasyMini  BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`  echo $FILE  echo "$PRODUCT v$VERSION Turn-On and Calibration Program" -echo "Copyright 2010 by Bdale Garbee.  Released under GPL v2" +echo "Copyright 2010 by Bdale Garbee.  Released under GPL v2+"  echo  echo "Expectations:" -echo "\t$PRODUCT v$VERSION powered from USB" -echo "\t\twith ST-Link-V2 cabled to debug header" +echo "\t$PRODUCT v$VERSION powered and connected to USB"  echo  case $# in @@ -49,17 +46,17 @@ esac  #  # Use released versions of everything  # -FLASH_FILE=~/altusmetrumllc/Binaries/loaders/easymini-v1.0-altos-flash-*.elf -ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v1.0-*.elf +FLASH_FILE=~/altusmetrumllc/Binaries/loaders/easymini-v2.0-altos-flash-*.bin +ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v2.0-*.elf  #FLASH_FILE=../src/$BASE-v$VERSION/flash-loader/$BASE-v$VERSION-altos-flash-*.elf  #ALTOS_FILE=../src/$BASE-v$VERSION/*.ihx -echo $FLASH_LPC $FLASH_FILE +echo $DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE -$FLASH_LPC $FLASH_FILE || exit 1 +#$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || exit 1 -sleep 1 +sleep 2  echo $USBLOAD $ALTOS_FILE diff --git a/ao-bringup/turnon_telebt b/ao-bringup/turnon_telebt index 509814d3..912ba459 100755 --- a/ao-bringup/turnon_telebt +++ b/ao-bringup/turnon_telebt @@ -1,10 +1,10 @@  #!/bin/sh -if [ -x /usr/bin/ao-flash-stm ]; then -	FLASH_STM=/usr/bin/ao-flash-stm +if [ -x /usr/bin/dfu-util ]; then +    DFU_UTIL=/usr/bin/dfu-util  else -	echo "Can't find ao-flash-stm!  Aborting." -	exit 1 +    echo "Can't find dfu-util! Aborting." +    exit 1  fi  if [ -x /usr/bin/ao-usbload ]; then @@ -14,38 +14,52 @@ else  	exit 1  fi -VERSION=3.0 +VERSION=4.0  REPO=~/altusmetrumllc/Binaries +PRODUCT=TeleBT -echo "TeleBT v$VERSION Turn-On and Calibration Program" -echo "Copyright 2015 by Bdale Garbee.  Released under GPL v2" +echo "$PRODUCT v$VERSION Turn-On and Calibration Program" +echo "Copyright 2017 by Bdale Garbee.  Released under GPL v3+"  echo  echo "Expectations:" -echo "\tTeleBT v$VERSION powered from USB" -echo "\t\twith ST-Link-V2 cabled to debug header" +echo "\t$PRODUCT v$VERSION attached by USB"  echo "\t\twith coax from UHF to frequency counter"  echo -echo -n "TeleBT-$VERSION serial number: " -read SERIAL -echo $FLASH_STM +case $# in +    1) +        SERIAL="$1" +        echo "$PRODUCT-$VERSION serial number: $SERIAL"  +        ;; +    0) +        echo -n "$PRODUCT-$VERSION serial number: " +        read SERIAL +        ;; +    *) +        echo "Usage: $0 <serial-number>" 1>&2 +        exit 1; +        ;; +esac + +FLASH_FILE=$REPO/loaders/telebt-v$VERSION-altos-flash-*.bin +ALTOS_FILE=$REPO/telebt-v$VERSION-*.elf -$FLASH_STM $REPO/loaders/telebt-v$VERSION*.elf || exit 1 +$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || exit 1 -sleep 5 +sleep 2 -$USBLOAD --serial=$SERIAL $REPO/telebt-v$VERSION*.elf || exit 1 +$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1 -sleep 5 +sleep 3 -dev=`ao-list | awk '/TeleBT-v'"$VERSION"'/ { print $3; exit(0); }'` +dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`  case "$dev" in  /dev/tty*) -	echo "TeleBT found on $dev" +	echo "$PRODUCT found on $dev"  	;;  *) -	echo 'No TeleBT-v'"$VERSION"' found' +	echo 'No '"$PRODUCT"'-v'"$VERSION"' found'  	exit 1  	;;  esac @@ -65,6 +79,15 @@ else  	exit 1  fi -echo "TeleBT-v$VERSION $SERIAL is ready to ship" +echo -n "checking BTLE functionality... " +btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }'` +if [ "$btdev" = "$SERIAL" ]; then +	echo "working!" +else +	echo "device not found" +	exit 1 +fi + +echo "$PRODUCT-v$VERSION $SERIAL is ready to ship"  exit $? diff --git a/ao-bringup/turnon_telebt_v3 b/ao-bringup/turnon_telebt_v3 new file mode 100755 index 00000000..509814d3 --- /dev/null +++ b/ao-bringup/turnon_telebt_v3 @@ -0,0 +1,70 @@ +#!/bin/sh + +if [ -x /usr/bin/ao-flash-stm ]; then +	FLASH_STM=/usr/bin/ao-flash-stm +else +	echo "Can't find ao-flash-stm!  Aborting." +	exit 1 +fi + +if [ -x /usr/bin/ao-usbload ]; then +	USBLOAD=/usr/bin/ao-usbload +else +	echo "Can't find ao-usbload!  Aborting." +	exit 1 +fi + +VERSION=3.0 +REPO=~/altusmetrumllc/Binaries + +echo "TeleBT v$VERSION Turn-On and Calibration Program" +echo "Copyright 2015 by Bdale Garbee.  Released under GPL v2" +echo +echo "Expectations:" +echo "\tTeleBT v$VERSION powered from USB" +echo "\t\twith ST-Link-V2 cabled to debug header" +echo "\t\twith coax from UHF to frequency counter" +echo +echo -n "TeleBT-$VERSION serial number: " +read SERIAL + +echo $FLASH_STM + +$FLASH_STM $REPO/loaders/telebt-v$VERSION*.elf || exit 1 + +sleep 5 + +$USBLOAD --serial=$SERIAL $REPO/telebt-v$VERSION*.elf || exit 1 + +sleep 5 + +dev=`ao-list | awk '/TeleBT-v'"$VERSION"'/ { print $3; exit(0); }'` + +case "$dev" in +/dev/tty*) +	echo "TeleBT found on $dev" +	;; +*) +	echo 'No TeleBT-v'"$VERSION"' found' +	exit 1 +	;; +esac + +echo 'E 0' > $dev + +SERIAL=$SERIAL ./cal-freq $dev + +echo 'E 1' > $dev + +echo -n "checking BlueTooth functionality... " +btdev=`hcitool scan | awk -F \- '/TeleBT/ { print $2 }'` +if [ "$btdev" = "$SERIAL" ]; then +	echo "working!" +else +	echo "device not found" +	exit 1 +fi + +echo "TeleBT-v$VERSION $SERIAL is ready to ship" + +exit $? diff --git a/ao-bringup/turnon_telemini b/ao-bringup/turnon_telemini index 1958de2a..23031481 100755 --- a/ao-bringup/turnon_telemini +++ b/ao-bringup/turnon_telemini @@ -7,8 +7,8 @@ else      exit 1  fi -if [ -x /usr/bin/ao-usbload ]; then -	USBLOAD=/usr/bin/ao-usbload +if which ao-usbload > /dev/null; then +	USBLOAD=`which ao-usbload`  else  	echo "Can't find ao-usbload!  Aborting."  	exit 1 diff --git a/ao-tools/ao-makebin/.gitignore b/ao-tools/ao-makebin/.gitignore new file mode 100644 index 00000000..91d4bf60 --- /dev/null +++ b/ao-tools/ao-makebin/.gitignore @@ -0,0 +1 @@ +ao-makebin diff --git a/configure.ac b/configure.ac index 3e6658e9..f4509b4c 100644 --- a/configure.ac +++ b/configure.ac @@ -18,13 +18,13 @@ dnl  dnl Process this file with autoconf to create configure.  AC_PREREQ(2.57) -AC_INIT([altos], 1.7) +AC_INIT([altos], 1.8)  ANDROID_VERSION=14  AC_CONFIG_SRCDIR([src/kernel/ao.h])  AM_INIT_AUTOMAKE([foreign dist-bzip2])  AM_MAINTAINER_MODE -RELEASE_DATE=2017-04-24 +RELEASE_DATE=2017-08-11  AC_SUBST(RELEASE_DATE)  VERSION_DASH=`echo $VERSION | sed 's/\./-/g'` @@ -34,8 +34,8 @@ AC_SUBST(ANDROID_VERSION)  dnl ==========================================================================  dnl Java library versions -ALTOSUILIB_VERSION=11 -ALTOSLIB_VERSION=11 +ALTOSUILIB_VERSION=12 +ALTOSLIB_VERSION=12  AC_SUBST(ALTOSLIB_VERSION)  AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package]) diff --git a/doc/Makefile b/doc/Makefile index 0d01279f..a09380cf 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -3,6 +3,7 @@  #  RELNOTES_INC=\ +	release-notes-1.8.inc \  	release-notes-1.7.inc \  	release-notes-1.6.8.inc \  	release-notes-1.6.5.inc \ @@ -167,7 +168,8 @@ OUTLINE_TXT_FILES=\  	telemega-outline.txt \  	telemetrum-outline.txt \  	telemini-v1-outline.txt \ -	telemini-v3-outline.txt +	telemini-v3-outline.txt \ +	telegps-outline.txt  OUTLINE_RAW_FILES=$(OUTLINE_TXT_FILES:.txt=.raw) diff --git a/doc/altusmetrum-docinfo.xml b/doc/altusmetrum-docinfo.xml index 2475b5f1..3c230f1a 100644 --- a/doc/altusmetrum-docinfo.xml +++ b/doc/altusmetrum-docinfo.xml @@ -47,6 +47,13 @@  <revhistory>    <?dbhtml filename="altusmetrum-revhistory.html"?>    <revision> +    <revnumber>1.8</revnumber> +    <date>12 Aug 2017</date> +    <revremark> +      Add support for TeleBT v4.0, updates in data analysis code +    </revremark> +  </revision> +  <revision>      <revnumber>1.7</revnumber>      <date>21 Apr 2017</date>      <revremark> diff --git a/doc/release-notes-1.8.inc b/doc/release-notes-1.8.inc new file mode 100644 index 00000000..0255c16b --- /dev/null +++ b/doc/release-notes-1.8.inc @@ -0,0 +1,33 @@ += Release Notes for Version 1.8 +:toc!: +:doctype: article + +	Version 1.8 includes support for our new TeleBT v4.0 ground +	station, updates for data analysis in our ground station +	software and bug fixes in in the flight software for all our +	boards and ground station interfaces. + +	== AltOS + +	AltOS New Features + +	* Add support for TeleBT v4.0 boards. + +	== AltosUI and TeleGPS Applications + +	AltosUI New Features + +	* Add support for TeleBT v4.0 hardware + +	* Rewrite graphing and export functions. This code now handles +          each data series separately so that graphs are drawn +          correctly. Smoothing now uses a filter that looks both +          forward and backwards in time to make computed speed and +          acceleration data more accurate. + +	AltosUI Bug Fixes + +	* Correct axis labeling of magnetic sensor in TeleMega and +          EasyMega. The Y and Z axes were flipped. + + diff --git a/doc/release-notes.inc b/doc/release-notes.inc index 86ce95d3..e52e36b5 100644 --- a/doc/release-notes.inc +++ b/doc/release-notes.inc @@ -2,6 +2,11 @@  == Release Notes  	:leveloffset: 2 +	include::release-notes-1.8.raw[] + +	<<<< + +	:leveloffset: 2  	include::release-notes-1.7.raw[]  	<<<< diff --git a/doc/telegps-outline.txt b/doc/telegps-outline.txt new file mode 100644 index 00000000..bd1495be --- /dev/null +++ b/doc/telegps-outline.txt @@ -0,0 +1,9 @@ += TeleGPS Outline and Hole Pattern +:doctype: article + +	This image, when printed, provides a precise template for the +	mounting holes in TeleGPS.  TeleGPS has overall dimensions +	of 1.000 x 1.500 inches, and the mounting holes are sized for +	use with 4-40 or M3 screws. + +	image::telegps.svg[align="center"] diff --git a/doc/telegps.svg b/doc/telegps.svg new file mode 100644 index 00000000..702265cc --- /dev/null +++ b/doc/telegps.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> + +<svg +       xmlns:dc="http://purl.org/dc/elements/1.1/" +   xmlns:cc="http://creativecommons.org/ns#" +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" +   xmlns:svg="http://www.w3.org/2000/svg" +   xmlns="http://www.w3.org/2000/svg" +   width="1.75in" +   height="1.25in" +   viewBox="0 0 175 125" +   preserveaspectratio="none" +   id="svg2" +   version="1.1"> +  <g transform="translate(12.5,12.5)" +     style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-size:20"> +    <!-- outline --> +    <rect width="150" height="100" x="0" y="0"/> +    <!-- holes --> +    <path d="M12.5,12.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/> +    <path d="M137.5,12.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/> +    <path d="M12.5,87.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/> +    <path d="M137.5,87.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/> +    <!-- arrow --> +    <path d="M25,50 l100,0"/> +    <path style="fill:#000000;stroke:none" d="M125,45 l10,5 l-10,5 z"/> +    <!-- label --> +    <text x="75" y="35" style="fill:#000000;stroke:none" text-anchor="middle">TeleGPS</text> +    <g transform="rotate(90)"> +      <text x="50" y="-133" style="fill:#000000;stroke:none" text-anchor="middle">UP</text> +    </g> +  </g> +</svg> diff --git a/libaltos/Makefile.am b/libaltos/Makefile.am index 8f69c1ad..69fe7a57 100644 --- a/libaltos/Makefile.am +++ b/libaltos/Makefile.am @@ -24,11 +24,15 @@ WINDOWS_SRC=\  WINDOWS_H=\  	libaltos.h -noinst_PROGRAMS=cjnitest +noinst_PROGRAMS=cjnitest btletest  cjnitest_SOURCES=cjnitest.c  cjnitest_LDADD=libaltos.la +btletest_SOURCES=btletest.c + +btletest_LDADD=-lbluetooth +  if MULTI_ARCH  altoslib_LTLIBRARIES+=libaltos32.la libaltos64.la diff --git a/libaltos/btletest.c b/libaltos/btletest.c new file mode 100644 index 00000000..0e325415 --- /dev/null +++ b/libaltos/btletest.c @@ -0,0 +1,183 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <termios.h> +#include <errno.h> +#include <unistd.h> +#include <ctype.h> +#include <dirent.h> +#include <bluetooth/bluetooth.h> +#include <bluetooth/hci.h> +#include <bluetooth/hci_lib.h> +#include <bluetooth/rfcomm.h> +#include <bluetooth/sdp.h> +#include <bluetooth/sdp_lib.h> +#include <bluetooth/l2cap.h> +#include <poll.h> + +#define ATT_OP_MTU_REQ		0x02 +#define ATT_OP_MTU_RESP		0x03 +#define ATT_OP_WRITE_CMD	0x52 +#define ATT_OP_HANDLE_NOTIFY	0x1b +#define CID_ATT			0x0004 +#define TX_ENDPOINT		0x003a +#define RX_ENDPOINT		0x0037 +#define RX_NOTIFY		0x0038 + +int +main(int argc, char **argv) +{ +	int sk; +	int psm; +	struct sockaddr_l2 src_addr = { 0 }; +	struct sockaddr_l2 dst_addr = { 0 }; +	char buf[1024]; +	struct pollfd	fd[2]; +	int n, i; +	char *btaddr; +	int	mtu; + +	btaddr = argc > 1 ? argv[1] : "D8:80:39:F3:4E:A5"; + +	sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); +	if (sk < 0) { +		perror("socket"); +		exit(1); +	} + +	src_addr.l2_family = AF_BLUETOOTH; +	/* Leave src_addr.l2_bdaddr all zeros */ +	src_addr.l2_cid = htobs(CID_ATT); +	src_addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; +	if (bind(sk, (struct sockaddr *) &src_addr, sizeof (src_addr)) < 0) { +		perror("bind"); +		exit(1); +	} + +	dst_addr.l2_family = AF_BLUETOOTH; +	str2ba(btaddr, &dst_addr.l2_bdaddr); +	dst_addr.l2_cid = htobs(CID_ATT); +	dst_addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; + +	if (connect(sk, (struct sockaddr *) &dst_addr, sizeof(dst_addr)) < 0) { +		perror("connect"); +		exit(1); +	} + +	buf[0] = ATT_OP_MTU_REQ; +	buf[1] = sizeof(buf) & 0xff; +	buf[2] = sizeof(buf) >> 8; +	n = write(sk, buf, 3); +	if (n != 3) { +		perror("write mtu\n"); +		exit(1); +	} + +	fd[0].fd = sk; +	fd[0].events = POLLIN; +	for (;;) { +		n = poll(fd, 1, 3000); +		if (n <= 0) { +			printf("timeout waiting for MTU response\n"); +			exit(1); +		} +		if (fd[0].revents & POLLIN) { +			n = read(sk, buf, sizeof(buf)); +			printf("read %d\n", n); +			for (i = 0; i < n; i++) +				printf("%02x\n", buf[i]); +			if (buf[0] == ATT_OP_MTU_RESP) { +				mtu = (buf[1] & 0xff) | ((buf[2] & 0xff) << 8); +				break; +			} +		} +	} +	printf("mtu %d\n", mtu); + +	buf[0] = ATT_OP_WRITE_CMD; +	buf[1] = RX_NOTIFY & 0xff; +	buf[2] = RX_NOTIFY >> 8; +	buf[3] = 1; +	n = write(sk, buf, 4); +	if (n != 4) { +		perror("write notify"); +		exit(1); +	} + +	fd[0].fd = 0; +	fd[0].events = POLLIN; +	fd[1].fd = sk; +	fd[1].events = POLLIN; + +	for (;;) { +		n = poll(fd, 2, -1); +		if (n == 0) +			continue; +		if (fd[0].revents & POLLIN) { +			char	*b; +			n = read(0, buf+3, sizeof(buf)-3); +			if (n < 0) { +				perror("read stdin"); +				exit(1); +			} +			if (n == 0) +				break; + +			b = buf; +			while (n > 0) { +				int this = n; +				if (this > mtu - 3) +					this = mtu - 3; + +				b[0] = ATT_OP_WRITE_CMD; +				b[1] = TX_ENDPOINT; +				b[2] = TX_ENDPOINT >> 8; +				if (write(sk, b, this + 3) != this + 3) { +					perror("write sk"); +					exit(1); +				} +				b += this; +				n -= this; +			} +		} +		if (fd[1].revents & POLLIN) { +			uint16_t	ch; + +			n = read(sk, buf, sizeof(buf)); +			if (n < 0) { +				perror("read sk"); +				exit(1); +			} +			if (n == 0) +				continue; +			ch = buf[1] | (buf[2] << 8); +			switch (buf[0]) { +			case ATT_OP_HANDLE_NOTIFY: +				if (ch == RX_ENDPOINT) +					write(1, buf+3, n-3); +				break; +			} +		} +		if (fd[1].revents & (POLLERR|POLLHUP)) +			break; +	} +	close(sk); + +	return 0; +} diff --git a/libaltos/cjnitest.c b/libaltos/cjnitest.c index 3a65c3d6..7e857275 100644 --- a/libaltos/cjnitest.c +++ b/libaltos/cjnitest.c @@ -1,5 +1,9 @@  #include <stdio.h>  #include "libaltos.h" +#include <string.h> + +#define HAS_BLUETOOTH 	1 +#define HAS_USB		1  static void  altos_puts(struct altos_file *file, char *string) @@ -19,6 +23,7 @@ main (int argc, char **argv)  	struct altos_bt_list	*bt_list;  	altos_init(); +#if HAS_USB  	list = altos_list_start();  	while (altos_list_next(list, &device)) {  		struct altos_file	*file; @@ -42,6 +47,7 @@ main (int argc, char **argv)  		altos_close(file);  	}  	altos_list_finish(list); +#endif  #if HAS_BLUETOOTH  	bt_list = altos_bt_list_start(8);  	while (altos_bt_list_next(bt_list, &bt_device)) { diff --git a/libaltos/libaltos_common.c b/libaltos/libaltos_common.c index dfafcc7a..f577de02 100644 --- a/libaltos/libaltos_common.c +++ b/libaltos/libaltos_common.c @@ -75,6 +75,27 @@ altos_putchar(struct altos_file *file, char c)  	return ret;  } +struct bt_vendor_map { +	char	vendor[10]; +	int	port; +}; + +static const struct bt_vendor_map altos_bt_vendor_map[] = { +	{ .vendor = "00:12:6f:", 1 },	/* Rayson */ +	{ .vendor = "8C:DE:52:", 6 },	/* ISSC */ +	{ .vendor = "D8:80:39:", 6 },	/* Microchip */ +}; + +#define NUM_BT_VENDOR_MAP	(sizeof altos_bt_vendor_map / sizeof altos_bt_vendor_map[0]) +#define BT_PORT_DEFAULT		1 + +int altos_bt_port(struct altos_bt_device *device) { +	unsigned i; +	for (i = 0; i < NUM_BT_VENDOR_MAP; i++) +		if (strncmp (device->addr, altos_bt_vendor_map[i].vendor, strlen(altos_bt_vendor_map[i].vendor)) == 0) +			return altos_bt_vendor_map[i].port; +	return BT_PORT_DEFAULT; +}  PUBLIC void  altos_free(struct altos_file *file) diff --git a/libaltos/libaltos_linux.c b/libaltos/libaltos_linux.c index 1cade72d..255b9773 100644 --- a/libaltos/libaltos_linux.c +++ b/libaltos/libaltos_linux.c @@ -26,6 +26,8 @@  #include <bluetooth/hci.h>  #include <bluetooth/hci_lib.h>  #include <bluetooth/rfcomm.h> +#include <bluetooth/sdp.h> +#include <bluetooth/sdp_lib.h>  static char *  cc_fullname (char *dir, char *file) @@ -380,6 +382,30 @@ bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))  bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))  #define hci_inquiry altos_hci_inquiry +bt_func(sdp_connect, sdp_session_t *, 0, (const bdaddr_t *src, const bdaddr_t *dst, uint32_t flags), (src, dst, flags)) +#define sdp_connect altos_sdp_connect + +bt_func(sdp_uuid16_create, uuid_t *, 0, (uuid_t *uuid, uint16_t data), (uuid, data)) +#define sdp_uuid16_create altos_sdp_uuid16_create + +bt_func(sdp_list_append, sdp_list_t *, 0, (sdp_list_t *list, void *d), (list, d)) +#define sdp_list_append altos_sdp_list_append + +bt_func(sdp_service_search_attr_req, int, -1, (sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list, sdp_list_t **rsp_list), (session, search, reqtype, attrid_list, rsp_list)) +#define sdp_service_search_attr_req altos_sdp_service_search_attr_req + +bt_func(sdp_uuid_to_proto, int, 0, (uuid_t *uuid), (uuid)) +#define sdp_uuid_to_proto altos_sdp_uuid_to_proto + +bt_func(sdp_get_access_protos, int, 0, (const sdp_record_t *rec, sdp_list_t **protos), (rec, protos)) +#define sdp_get_access_protos altos_sdp_get_access_protos + +bt_func(sdp_get_proto_port, int, 0, (const sdp_list_t *list, int proto), (list, proto)) +#define sdp_get_proto_port altos_sdp_get_proto_port + +bt_func(sdp_close, int, 0, (sdp_session_t *session), (session)) +#define sdp_close altos_sdp_close +  struct altos_bt_list {  	inquiry_info	*ii;  	int		sock; @@ -478,7 +504,68 @@ altos_bt_open(struct altos_bt_device *device)  	struct sockaddr_rc 	addr = { 0 };  	int			status, i;  	struct altos_file_posix	*file; +	sdp_session_t		*session = NULL; +	int			channel = 0; +	if (str2ba(device->addr, &addr.rc_bdaddr) < 0) { +		altos_set_last_posix_error(); +		goto no_file; +	} + +#if 0 +	/* +	 * Search for the RFCOMM service to get the right channel +	 */ +	session = sdp_connect(BDADDR_ANY, &addr.rc_bdaddr, SDP_RETRY_IF_BUSY); + +	if (session) { +		static const uint8_t svc_uuid_int[] = { +			0, 0, 0, 0, 0, 0, 0, 0, +			0, 0, 0, 0, 0, 0, 0x11, 0x01 +		}; +		int			err; +		uuid_t			svc_uuid; +		uint32_t		range; +		sdp_list_t		*search_list, *attrid_list; +		sdp_list_t		*response_list = NULL, *r; +		sdp_uuid16_create(&svc_uuid, PUBLIC_BROWSE_GROUP); +		search_list = sdp_list_append(NULL, &svc_uuid); + +		range = 0x0000ffff; +		attrid_list = sdp_list_append(NULL, &range); + +		err = sdp_service_search_attr_req(session, search_list, +						  SDP_ATTR_REQ_RANGE, attrid_list, &response_list); + +		if (err >= 0) { +			for (r = response_list; r; r = r->next) { +				sdp_record_t *rec = (sdp_record_t*) r->data; +				sdp_list_t *proto_list; +				sdp_list_t *access = NULL; +				int proto; + +				proto = sdp_uuid_to_proto(&rec->svclass); + +				if (proto == SERIAL_PORT_SVCLASS_ID) { +					sdp_get_access_protos(rec, &access); +					if (access) { +						int this_chan = sdp_get_proto_port(access, RFCOMM_UUID); +						if (this_chan) +							channel = this_chan; +					} +				} +			} +		} + +		/* Leave the session open so we don't disconnect from the device before opening +		 * the RFCOMM channel +		 */ +	} +#endif +	if (channel == 0) +		channel = altos_bt_port(device); + +	/* Connect to the channel */  	file = calloc(1, sizeof (struct altos_file_posix));  	if (!file) {  		errno = ENOMEM; @@ -486,11 +573,7 @@ altos_bt_open(struct altos_bt_device *device)  		goto no_file;  	}  	addr.rc_family = AF_BLUETOOTH; -	addr.rc_channel = 1; -	if (str2ba(device->addr, &addr.rc_bdaddr) < 0) { -		altos_set_last_posix_error(); -		goto no_sock; -	} +	addr.rc_channel = channel;  	for (i = 0; i < 5; i++) {  		file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); @@ -507,10 +590,16 @@ altos_bt_open(struct altos_bt_device *device)  		close(file->fd);  		usleep(100 * 1000);  	} + +  	if (status < 0) {  		altos_set_last_posix_error();  		goto no_link;  	} + +	if (session) +		sdp_close(session); +  	usleep(100 * 1000);  #ifdef USE_POLL @@ -524,6 +613,8 @@ no_link:  no_sock:  	free(file);  no_file: +	if (session) +		sdp_close(session);  	return NULL;  } diff --git a/libaltos/libaltos_private.h b/libaltos/libaltos_private.h index f8e5231b..ee3dd708 100644 --- a/libaltos/libaltos_private.h +++ b/libaltos/libaltos_private.h @@ -61,4 +61,7 @@ altos_flush(struct altos_file *file);  int  altos_fill(struct altos_file *file, int timeout); +int +altos_bt_port(struct altos_bt_device *device); +  #endif /* _LIBALTOS_PRIVATE_H_ */ diff --git a/libaltos/libaltos_windows.c b/libaltos/libaltos_windows.c index e53aa72b..4f9f1807 100644 --- a/libaltos/libaltos_windows.c +++ b/libaltos/libaltos_windows.c @@ -747,7 +747,7 @@ altos_bt_open(struct altos_bt_device *device)  	memset(&sockaddr_bth, '\0', sizeof (sockaddr_bth));  	sockaddr_bth.addressFamily = AF_BTH;  	sockaddr_bth.btAddr = str2ba(device->addr); -	sockaddr_bth.port = 1; +	sockaddr_bth.port = altos_bt_port(device);  	ret = connect(file->socket, (SOCKADDR *) &sockaddr_bth, sizeof (sockaddr_bth)); diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 7ad2c102..52b62358 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -14,18 +14,14 @@ micropeakdir=$(datadir)/java  micropeak_JAVA= \  	MicroPeak.java \  	MicroData.java \ -	MicroDataPoint.java \  	MicroDownload.java \  	MicroExport.java \  	MicroFile.java \  	MicroFrame.java \ -	MicroGraph.java \  	MicroRaw.java \  	MicroSave.java \  	MicroSerial.java \  	MicroSerialLog.java \ -	MicroStats.java \ -	MicroStatsTable.java \  	MicroFileChooser.java \  	MicroDeviceDialog.java \  	MicroUSB.java diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index b45ad2c1..70492a07 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -21,91 +21,28 @@ package org.altusmetrum.micropeak;  import java.lang.*;  import java.io.*;  import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; -class MicroIterator implements Iterator<MicroDataPoint> { -	int		i; -	MicroData	data; - -	public boolean hasNext() { -		return i < data.pressures.length; -	} - -	public MicroDataPoint next() { -		return new MicroDataPoint(data, i++); -	} - -	public MicroIterator (MicroData data) { -		this.data = data; -		i = 0; -	} - -	public void remove() { -	} -} - -class MicroIterable implements Iterable<MicroDataPoint> { - -	MicroData	data; - -	public Iterator<MicroDataPoint> iterator() { -		return new MicroIterator(data); -	} - -	public MicroIterable(MicroData data) { -		this.data = data; -	} -} - -class MicroUIIterator implements Iterator<AltosUIDataPoint> { -	int		i; -	MicroData	data; - -	public boolean hasNext() { -		return i < data.pressures.length; -	} - -	public AltosUIDataPoint next() { -		return new MicroDataPoint(data, i++); -	} - -	public MicroUIIterator (MicroData data) { -		this.data = data; -		i = 0; -	} - -	public void remove() { -	} -} - -class MicroUIIterable implements Iterable<AltosUIDataPoint> { -	MicroData	data; - -	public Iterator<AltosUIDataPoint> iterator() { -		return new MicroUIIterator(data); -	} - -	public MicroUIIterable(MicroData data) { -		this.data = data; -	} -} - -public class MicroData implements AltosUIDataSet { +public class MicroData {  	public int		ground_pressure;  	public int		min_pressure; -	public int[]		pressures; + +	AltosUIFlightSeries	flight_series; +	AltosFlightStats	flight_stats; +	AltosCalData		cal_data; +  	private double		time_step; -	private double		ground_altitude;  	private ArrayList<Integer>	bytes;  	public int		log_id;  	String			name; -	MicroStats		stats;  	public static final int LOG_ID_MICROPEAK = 0;  	public static final int LOG_ID_MICROKITE = 1; +	public static final int LOG_ID_MICROPEAK2 = 2; -	public static final double CLOCK = 0.096; +	public static final double CLOCK_MP1 = 0.096; +	public static final double CLOCK_MP2 = 0.1;  	public class FileEndedException extends Exception {  	} @@ -211,69 +148,45 @@ public class MicroData implements AltosUIDataSet {  		return Math.abs (target - a) < Math.abs(target - b);  	} +	public double altitude(double time) { +		if (flight_series.altitude_series == null) +			return 0.0; +		return flight_series.altitude_series.value(time); +	} +  	public double altitude(int i) { -		return AltosConvert.pressure_to_altitude(pressures[i]); +		return altitude(time(i));  	}  	public String name() {  		return name;  	} -	public Iterable<AltosUIDataPoint> dataPoints() { -		return new MicroUIIterable(this); -	} - -	public Iterable<MicroDataPoint> points() { -		return new MicroIterable(this); -	} - -	int fact(int n) { -		if (n == 0) -			return 1; -		return n * fact(n-1); -	} +	public double pressure(int i) { +		if (flight_series.pressure_series == null) +			return 0.0; -	int choose(int n, int k) { -		return fact(n) / (fact(k) * fact(n-k)); +		return flight_series.pressure_series.value(time(i));  	} +	public double height(double time) { +		if (flight_series.height_series == null) +			return 0.0; -	public double avg_altitude(int center, int dist) { -		int	start = center - dist; -		int	stop = center + dist; - -		if (start < 0) -			start = 0; -		if (stop >= pressures.length) -			stop = pressures.length - 1; - -		double	sum = 0; -		double	div = 0; - -		int	n = dist * 2; - -		for (int i = start; i <= stop; i++) { -			int	k = i - (center - dist); -			int	c = choose (n, k); - -			sum += c * pressures[i]; -			div += c; -		} - -		double pres = sum / div; - -		double alt = AltosConvert.pressure_to_altitude(pres); -		return alt; +		return flight_series.height_series.value(time);  	} -	public double pressure(int i) { -		return pressures[i]; +	public double height(int i) { +		return height(time(i));  	} -	public double height(int i) { -		return altitude(i) - ground_altitude; +	public int length() { +		if (flight_series.pressure_series == null) +			return 0; +		return flight_series.pressure_series.size();  	} +	/* Use the recorded apogee pressure for stats so that it agrees with the device */  	public double apogee_pressure() {  		return min_pressure;  	} @@ -283,31 +196,27 @@ public class MicroData implements AltosUIDataSet {  	}  	public double apogee_height() { -		return apogee_altitude() - ground_altitude; +		return apogee_altitude() - cal_data.ground_altitude;  	} -	static final int speed_avg = 3; -	static final int accel_avg = 5; - -	private double avg_speed(int center, int dist) { -		if (center == 0) -			return 0; - -		double ai = avg_altitude(center, dist); -		double aj = avg_altitude(center - 1, dist); -		double s = (ai - aj) / time_step; - -		return s; +	public double speed(double time) { +		if (flight_series.speed_series == null) +			return 0.0; +		return flight_series.speed_series.value(time);  	}  	public double speed(int i) { -		return avg_speed(i, speed_avg); +		return speed(time(i)); +	} + +	public double acceleration(double time) { +		if (flight_series.accel_series == null) +			return 0.0; +		return flight_series.accel_series.value(time);  	}  	public double acceleration(int i) { -		if (i == 0) -			return 0; -		return (avg_speed(i, accel_avg) - avg_speed(i-1, accel_avg)) / time_step; +		return acceleration(time(i));  	}  	public double time(int i) { @@ -323,18 +232,24 @@ public class MicroData implements AltosUIDataSet {  	public void export (Writer f) throws IOException {  		PrintWriter	pw = new PrintWriter(f);  		pw.printf("  Time, Press(Pa), Height(m), Height(f), Speed(m/s), Speed(mph), Speed(mach), Accel(m/s²), Accel(ft/s²),  Accel(g)\n"); -		for (MicroDataPoint point : points()) { + +		for (AltosTimeValue ptv : flight_series.pressure_series) { + +			double height = height(ptv.time); +			double speed = speed(ptv.time); +			double accel = acceleration(ptv.time); +  			pw.printf("%6.3f,%10.0f,%10.1f,%10.1f,%11.2f,%11.2f,%12.4f,%12.2f,%13.2f,%10.4f\n", -				  point.time, -				  point.pressure, -				  point.height, -				  AltosConvert.meters_to_feet(point.height), -				  point.speed, -				  AltosConvert.meters_to_mph(point.speed), -				  AltosConvert.meters_to_mach(point.speed), -				  point.accel, -				  AltosConvert.meters_to_feet(point.accel), -				  AltosConvert.meters_to_g(point.accel)); +				  ptv.time, +				  ptv.value, +				  height, +				  AltosConvert.meters_to_feet(height), +				  speed, +				  AltosConvert.meters_to_mph(speed), +				  AltosConvert.meters_to_mach(speed), +				  accel, +				  AltosConvert.meters_to_feet(accel), +				  AltosConvert.meters_to_g(accel));  		}  	} @@ -342,9 +257,20 @@ public class MicroData implements AltosUIDataSet {  		this.name = name;  	} +	public MicroData() { +		ground_pressure = 101000; +		min_pressure = 101000; +		cal_data = new AltosCalData(); +		flight_series = new AltosUIFlightSeries(cal_data); +	} +  	public MicroData (InputStream f, String name) throws IOException, InterruptedException, NonHexcharException, FileEndedException {  		this.name = name;  		bytes = new ArrayList<Integer>(); + +		cal_data = new AltosCalData(); +		flight_series = new AltosUIFlightSeries(cal_data); +  		if (!find_header(f))  			throw new IOException("No MicroPeak data header found");  		try { @@ -355,11 +281,30 @@ public class MicroData implements AltosUIDataSet {  			log_id = nsamples >> 12;  			nsamples &= 0xfff; -			pressures = new int[nsamples + 1]; -			ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); +			cal_data.set_ground_pressure(ground_pressure); + +			switch (log_id) { +			case LOG_ID_MICROPEAK: +				time_step = 2 * CLOCK_MP1; +				break; +			case LOG_ID_MICROKITE: +				time_step = 200 * CLOCK_MP1; +				break; +			case LOG_ID_MICROPEAK2: +				time_step = CLOCK_MP2; +				break; +			default: +				throw new IOException(String.format("Unknown device type: %d", log_id)); +			} +			cal_data.set_ticks_per_sec(1/time_step); +			cal_data.set_tick(0); +			cal_data.set_boost_tick(); +  			int cur = ground_pressure; -			pressures[0] = cur; +			cal_data.set_tick(0); +			flight_series.set_time(cal_data.time()); +			flight_series.set_pressure(cur);  			for (int i = 0; i < nsamples; i++) {  				int	k = get_16(f);  				int	same = mix_in(cur, k); @@ -378,33 +323,40 @@ public class MicroData implements AltosUIDataSet {  						cur = down;  				} -				pressures[i+1] = cur; +				cal_data.set_tick(i+1); +				flight_series.set_time(cal_data.time()); +				flight_series.set_pressure(cur);  			} +			flight_series.finish(); + +			/* Build states */ + +			flight_series.set_time(0); +			flight_series.set_state(AltosLib.ao_flight_boost); + +			flight_series.set_time(flight_series.speed_series.max().time); +			flight_series.set_state(AltosLib.ao_flight_coast); + +			flight_series.set_time(flight_series.height_series.max().time); +			flight_series.set_state(AltosLib.ao_flight_drogue); + +			cal_data.set_tick(nsamples); +			flight_series.set_time(cal_data.time()); +			flight_series.set_state(AltosLib.ao_flight_landed); + +			flight_series.finish(); + +			flight_stats = new AltosFlightStats(flight_series); +  			int current_crc = swap16(~file_crc & 0xffff);  			int crc = get_16(f);  			crc_valid = crc == current_crc; -			switch (log_id) { -			case LOG_ID_MICROPEAK: -				time_step = 2 * CLOCK; -				break; -			case LOG_ID_MICROKITE: -				time_step = 200 * CLOCK; -				break; -			} -			stats = new MicroStats(this);  		} catch (FileEndedException fe) {  			throw new IOException("File Ended Unexpectedly");  		}  	} -	public MicroData() { -		ground_pressure = 101000; -		min_pressure = 101000; -		pressures = new int[1]; -		pressures[0] = 101000; -	} -  } diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java deleted file mode 100644 index 42079291..00000000 --- a/micropeak/MicroDataPoint.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright © 2012 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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. - */ - -package org.altusmetrum.micropeak; - -import org.altusmetrum.altosuilib_11.*; - -public class MicroDataPoint implements AltosUIDataPoint { -	public double		time; -	public double		pressure; -	public double		height; -	public double		speed; -	public double		accel; -	public MicroStats	stats; - -	public static final int data_height = 0; -	public static final int data_speed = 1; -	public static final int data_accel = 2; -	public static final int data_state = 3; - -	public double x() { -		return time; -	} - -	public double y(int index) { -		switch (index) { -		case data_height: -			return height; -		case data_speed: -			return speed; -		case data_accel: -			return accel; -		default: -			return 0; -		} -	} - -	public int id(int index) { -		if (index == data_state) { -			return stats.state(time); -		} -		return 0; -	} - -	public String id_name(int index) { -		if (index == data_state) -			return stats.state_name(time); -		return ""; -	} - -	public MicroDataPoint (double pressure, double height, double speed, double accel, double time, MicroStats stats) { -		this.pressure = pressure; -		this.height = height; -		this.speed = speed; -		this.accel = accel; -		this.time = time; -		this.stats = stats; -	} - -	public MicroDataPoint(MicroData data, int i) { -		this(data.pressure(i), -		     data.height(i), -		     data.speed(i), -		     data.acceleration(i), -		     data.time(i), -		     data.stats); -	} -}
\ No newline at end of file diff --git a/micropeak/MicroDeviceDialog.java b/micropeak/MicroDeviceDialog.java index 010612a0..db2662a0 100644 --- a/micropeak/MicroDeviceDialog.java +++ b/micropeak/MicroDeviceDialog.java @@ -22,7 +22,7 @@ import javax.swing.*;  import java.awt.*;  import java.awt.event.*;  import java.util.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroDeviceDialog extends AltosDeviceDialog { diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java index 2326ea08..e5f54821 100644 --- a/micropeak/MicroDownload.java +++ b/micropeak/MicroDownload.java @@ -24,8 +24,8 @@ import javax.swing.*;  import java.io.*;  import java.util.concurrent.*;  import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {  	MicroPeak	owner; diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java index f1062681..36700e75 100644 --- a/micropeak/MicroExport.java +++ b/micropeak/MicroExport.java @@ -24,8 +24,8 @@ import java.util.ArrayList;  import java.awt.*;  import javax.swing.*;  import javax.swing.filechooser.FileNameExtensionFilter; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroExport extends JFileChooser { diff --git a/micropeak/MicroFile.java b/micropeak/MicroFile.java index b341f350..20f6db55 100644 --- a/micropeak/MicroFile.java +++ b/micropeak/MicroFile.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;  import java.io.*;  import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroFile { diff --git a/micropeak/MicroFileChooser.java b/micropeak/MicroFileChooser.java index c068244b..85f7aed4 100644 --- a/micropeak/MicroFileChooser.java +++ b/micropeak/MicroFileChooser.java @@ -21,8 +21,8 @@ package org.altusmetrum.micropeak;  import javax.swing.*;  import javax.swing.filechooser.FileNameExtensionFilter;  import java.io.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroFileChooser extends JFileChooser {  	JFrame	frame; diff --git a/micropeak/MicroFrame.java b/micropeak/MicroFrame.java index b6f1f76d..d9ad8404 100644 --- a/micropeak/MicroFrame.java +++ b/micropeak/MicroFrame.java @@ -22,7 +22,7 @@ import java.awt.*;  import java.awt.event.*;  import javax.swing.*;  import java.util.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroFrame extends AltosUIFrame {  	static String[] micro_icon_names = { diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java deleted file mode 100644 index 64a43bd8..00000000 --- a/micropeak/MicroGraph.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright © 2012 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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. - */ - -package org.altusmetrum.micropeak; - -import java.io.*; -import java.util.ArrayList; - -import java.awt.*; -import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; - -import org.jfree.ui.*; -import org.jfree.chart.*; -import org.jfree.chart.plot.*; -import org.jfree.chart.axis.*; -import org.jfree.chart.renderer.*; -import org.jfree.chart.renderer.xy.*; -import org.jfree.chart.labels.*; -import org.jfree.data.xy.*; -import org.jfree.data.*; - -public class MicroGraph extends AltosUIGraph { - -	static final private Color height_color = new Color(194,31,31); -	static final private Color speed_color = new Color(31,194,31); -	static final private Color accel_color = new Color(31,31,194); -	static final private Color state_color = new Color(3,3,3); - -	public MicroGraph(AltosUIEnable enable) { -		super(enable); - -		addSeries("Height", MicroDataPoint.data_height, AltosConvert.height, height_color); -		addSeries("Speed", MicroDataPoint.data_speed, AltosConvert.speed, speed_color); -		addSeries("Acceleration", MicroDataPoint.data_accel, AltosConvert.accel, accel_color); -		addMarker("State", MicroDataPoint.data_state, state_color); -	} -}
\ No newline at end of file diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 9023f452..607bf20c 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -24,18 +24,17 @@ import javax.swing.*;  import java.io.*;  import java.util.concurrent.*;  import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {  	File		filename; -	MicroGraph	graph; +	AltosGraph	graph;  	AltosUIEnable	enable; -	MicroStatsTable	statsTable; +	AltosFlightStatsTable	statsTable;  	MicroRaw	raw;  	MicroData	data; -	MicroStats	stats;  	Container	container;  	JTabbedPane	pane;  	static int	number_of_windows; @@ -47,9 +46,12 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene  			return mp.SetData(data);  		}  		this.data = data; -		stats = new MicroStats(data); -		graph.setDataSet(data); -		statsTable.setStats(stats); +		if (data.flight_series == null) +			System.out.printf("no data in flight\n"); +		if (data.flight_stats == null) +			System.out.printf("no stats in flight\n"); +		graph.set_data(data.flight_stats, data.flight_series); +		statsTable.set_stats(data.flight_stats);  		raw.setData(data);  		setTitle(data.name);  		return this; @@ -265,8 +267,9 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene  		});  		enable = new AltosUIEnable(); -		graph = new MicroGraph(enable); -		statsTable = new MicroStatsTable(); + +		graph = new AltosGraph(enable); +		statsTable = new AltosFlightStatsTable();  		raw = new MicroRaw();  		pane.add(graph.panel, "Graph");  		pane.add(enable, "Configure Graph"); @@ -324,8 +327,9 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene  						CommandExport(file);  					opened = true;  				} catch (Exception e) { -					System.err.printf("Error processing \"%s\": %s\n", -							  file.getName(), e.getMessage()); +					System.err.printf("Error processing \"%s\": %s %s\n", +							  file.getName(), e.toString(), e.getMessage()); +					e.printStackTrace();  				}  			}  		} diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java index f00d7ea3..d1d5d076 100644 --- a/micropeak/MicroRaw.java +++ b/micropeak/MicroRaw.java @@ -21,8 +21,8 @@ package org.altusmetrum.micropeak;  import java.awt.*;  import java.io.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroRaw extends JTextArea { @@ -30,7 +30,7 @@ public class MicroRaw extends JTextArea {  		StringWriter	sw = new StringWriter();  		try {  			data.export(sw); -			setRows(data.pressures.length + 1); +			setRows(data.length());  			setText(sw.toString());  		} catch (IOException ie) {  			setText(String.format("Error writing data: %s", ie.getMessage())); diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java index 5dda5b8c..9da76914 100644 --- a/micropeak/MicroSave.java +++ b/micropeak/MicroSave.java @@ -25,8 +25,8 @@ import javax.swing.filechooser.FileNameExtensionFilter;  import java.io.*;  import java.util.concurrent.*;  import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroSave extends JFileChooser { diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java index 43dfd18b..c1b2a7ad 100644 --- a/micropeak/MicroSerial.java +++ b/micropeak/MicroSerial.java @@ -21,7 +21,7 @@ package org.altusmetrum.micropeak;  import java.util.*;  import java.io.*;  import libaltosJNI.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroSerial extends InputStream {  	SWIGTYPE_p_altos_file	file; diff --git a/micropeak/MicroSerialLog.java b/micropeak/MicroSerialLog.java index 2e6dd236..d33a36b3 100644 --- a/micropeak/MicroSerialLog.java +++ b/micropeak/MicroSerialLog.java @@ -21,7 +21,7 @@ package org.altusmetrum.micropeak;  import java.util.*;  import java.io.*;  import libaltosJNI.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*;  public interface MicroSerialLog { diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java deleted file mode 100644 index b9637536..00000000 --- a/micropeak/MicroStats.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright © 2011 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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. - */ - -package org.altusmetrum.micropeak; - -import java.io.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; - -public class MicroStats { -	double		coast_height; -	double		coast_time; - -	double		apogee_height; -	double		apogee_time; - -	double		landed_height; -	double		landed_time; - -	double		max_speed; -	double		max_accel; - -	MicroData	data; - -	void find_landing() { -		landed_height = 0; - -		for (MicroDataPoint point : data.points()) { -			landed_height = point.height; -			landed_time = point.time; -		} - -		boolean above = false; -		for (MicroDataPoint point : data.points()) { -			if (point.height > landed_height + 10) { -				above = true; -			} else { -				if (above && point.height < landed_height + 2) { -					above = false; -					landed_time = point.time; -				} -			} -		} -	} - -	void find_apogee() { -		apogee_height = data.apogee_height(); -		double searched_apogee = 0; -		apogee_time = 0; -		 -		/* This just finds the apogee time -- we've recorded the -		 * peak altitude separately in eeprom, and that could -		 * have occurred after the eeprom was full. -		 */ -		for (MicroDataPoint point : data.points()) { -			if (point.height > searched_apogee) { -				searched_apogee = point.height; -				apogee_time = point.time; -			} -		} -	} - -	void find_coast() { -		coast_height = 0; -		coast_time = 0; - -		for (MicroDataPoint point : data.points()) { -			if (point.accel < -9.8) -				break; -			coast_time = point.time; -			coast_height = point.height; -		} -	} - -	void find_max_speed() { -		max_speed = 0; -		for (MicroDataPoint point : data.points()) { -			if (point.time > apogee_time) -				break; -			if (point.speed > max_speed) -				max_speed = point.speed; -		} -	} - -	void find_max_accel() { -		max_accel = 0; -		for (MicroDataPoint point : data.points()) { -			if (point.time > apogee_time) -				break; -			if (point.accel > max_accel) -				max_accel = point.accel; -		} -	} - -	double boost_duration() { -		return coast_time; -	} - -	double boost_height() { -		return coast_height; -	} - -	double	boost_speed() { -		return coast_height / coast_time; -	} - -	double boost_accel() { -		return boost_speed() / boost_duration(); -	} - -	double coast_duration() { -		return apogee_time - coast_time; -	} - -	double coast_height() { -		return apogee_height - coast_height; -	} - -	double coast_speed() { -		return coast_height() / coast_duration(); -	} - -	double coast_accel() { -		return coast_speed() / coast_duration(); -	} - -	double descent_duration() { -		return landed_time - apogee_time; -	} - -	double descent_height() { -		return apogee_height - landed_height; -	} - -	double descent_speed() { -		return descent_height() / descent_duration(); -	} - -	public static final int state_startup = -1; -	public static final int state_pad = 0; -	public static final int state_boost = 1; -	public static final int state_coast = 2; -	public static final int state_descent = 3; -	public static final int state_landed = 4; - -	static final String state_names[] = { -		"pad", -		"boost", -		"coast", -		"descent", -		"landed" -	}; - -	public int state(double t) { -		if (t >= landed_time) -			return state_landed; -		if (t >= apogee_time) -			return state_descent; -		if (t >= coast_time) -			return state_coast; -		if (t >= 0) -			return state_boost; -		return state_pad; -	} - -	public static String state_name(int state) { -		if (state < 0 || state > state_landed) -			return "unknown"; -		return state_names[state]; -	} - -	public String state_name(double t) { -		return state_name(state(t)); -	} - -	public MicroStats(MicroData data) { - -		this.data = data; - -		find_coast(); -		find_apogee(); -		find_landing(); -		find_max_speed(); -		find_max_accel(); -	} - -	public MicroStats() { -		this(new MicroData()); -	} -} diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java deleted file mode 100644 index e095e3a4..00000000 --- a/micropeak/MicroStatsTable.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright © 2011 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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. - */ - -package org.altusmetrum.micropeak; - -import java.awt.*; -import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; - -public class MicroStatsTable extends JComponent implements AltosFontListener { -	GridBagLayout	layout; - -	class MicroStat { -		JLabel		label; -		JTextField[]	texts; - -		public void set_values(String ... values) { -			for (int j = 0; j < values.length; j++) { -				texts[j].setText(values[j]); -			} -		} - -		public void set_font() { -			for (int j = 0; j < texts.length; j++) -				texts[j].setFont(AltosUILib.value_font); -			label.setFont(AltosUILib.label_font); -		} - -		public MicroStat(GridBagLayout layout, int y, String label_text, String ... values) { -			GridBagConstraints	c = new GridBagConstraints(); -			c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); -			c.weighty = 1; - -			label = new JLabel(label_text); -			label.setFont(AltosUILib.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); - -			texts = new JTextField[values.length]; -			for (int j = 0; j < values.length; j++) { -				JTextField value = new JTextField(values[j]); -				value.setEditable(false); -				value.setFont(AltosUILib.value_font); -				value.setHorizontalAlignment(SwingConstants.RIGHT); -				texts[j] = value; -				c.gridx = j+1; c.gridy = y; -				c.anchor = GridBagConstraints.EAST; -				c.fill = GridBagConstraints.BOTH; -				c.weightx = 1; -				layout.setConstraints(value, c); -				add(value); -			} -		} -	} - -	MicroStat	max_height, max_speed; -	MicroStat	max_accel, avg_accel; -	MicroStat	boost_duration; -	MicroStat	coast_duration; -	MicroStat	descent_speed; -	MicroStat	descent_duration; -	MicroStat	flight_time; -	 -	public void setStats(MicroStats stats) { -		max_height.set_values(String.format("%7.1f m", stats.apogee_height), -				      String.format("%7.1f ft", AltosConvert.meters_to_feet(stats.apogee_height))); -		max_speed.set_values(String.format("%7.1f m/s", stats.max_speed), -				     String.format("%7.1f mph", AltosConvert.meters_to_mph(stats.max_speed)), -				     String.format("Mach %7.3f", AltosConvert.meters_to_mach(stats.max_speed))); -		max_accel.set_values(String.format("%7.1f m/s²", stats.max_accel), -				     String.format("%7.1f ft/s²", AltosConvert.meters_to_feet(stats.max_accel)), -				     String.format("%7.3f G", AltosConvert.meters_to_g(stats.max_accel))); -		avg_accel.set_values(String.format("%7.1f m/s²", stats.boost_accel(), -						   String.format("%7.1f ft/s²", AltosConvert.meters_to_feet(stats.boost_accel())), -						   String.format("%7.3f G", AltosConvert.meters_to_g(stats.boost_accel())))); -		boost_duration.set_values(String.format("%6.1f s", stats.boost_duration())); -		coast_duration.set_values(String.format("%6.1f s", stats.coast_duration())); -		descent_speed.set_values(String.format("%7.1f m/s", stats.descent_speed()), -					 String.format("%7.1f ft/s", AltosConvert.meters_to_feet(stats.descent_speed()))); -		descent_duration.set_values(String.format("%6.1f s", stats.descent_duration())); -		flight_time.set_values(String.format("%6.1f s", stats.landed_time)); -	} - -	public void set_font() { -		max_height.set_font(); -		max_speed.set_font(); -		max_accel.set_font(); -		avg_accel.set_font(); -		boost_duration.set_font(); -		coast_duration.set_font(); -		descent_speed.set_font(); -		descent_duration.set_font(); -		flight_time.set_font(); -	} - -	public void font_size_changed(int font_size) { -		set_font(); -	} - -	public MicroStatsTable(MicroStats stats) { -		layout = new GridBagLayout(); - -		setLayout(layout); -		int y = 0; -		max_height = new MicroStat(layout, y++, "Maximum height", -					   String.format("%7.1f m", stats.apogee_height), -					   String.format("%7.1f ft", AltosConvert.meters_to_feet(stats.apogee_height))); -		max_speed = new MicroStat(layout, y++, "Maximum speed", -					  String.format("%7.1f m/s", stats.max_speed), -					  String.format("%7.1f mph", AltosConvert.meters_to_mph(stats.max_speed)), -					  String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); -		max_accel = new MicroStat(layout, y++, "Maximum boost acceleration", -					  String.format("%7.1f m/s²", stats.max_accel), -					  String.format("%7.1f ft/s²", AltosConvert.meters_to_feet(stats.max_accel)), -					  String.format("%7.3f G", AltosConvert.meters_to_g(stats.max_accel))); -		avg_accel = new MicroStat(layout, y++, "Average boost acceleration", -					  String.format("%7.1f m/s²", stats.boost_accel(), -							String.format("%7.1f ft/s²", AltosConvert.meters_to_feet(stats.boost_accel())), -							String.format("%7.3f G", AltosConvert.meters_to_g(stats.boost_accel())))); -		boost_duration = new MicroStat(layout, y++, "Boost duration", -					       String.format("%6.1f s", stats.boost_duration())); -		coast_duration = new MicroStat(layout, y++, "Coast duration", -					       String.format("%6.1f s", stats.coast_duration())); -		descent_speed = new MicroStat(layout, y++, "Descent rate", -					      String.format("%7.1f m/s", stats.descent_speed()), -					      String.format("%7.1f ft/s", AltosConvert.meters_to_feet(stats.descent_speed()))); -		descent_duration = new MicroStat(layout, y++, "Descent duration", -						 String.format("%6.1f s", stats.descent_duration())); -		flight_time = new MicroStat(layout, y++, "Flight Time", -					    String.format("%6.1f s", stats.landed_time)); -		set_font(); - -		AltosUIPreferences.register_font_listener(this); -	} - -	public void tell_closing() { -		AltosUIPreferences.unregister_font_listener(this); -	} - -	public MicroStatsTable() { -		this(new MicroStats()); -	} -	 -} diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java index 4ab5fcc9..a2db3835 100644 --- a/micropeak/MicroUSB.java +++ b/micropeak/MicroUSB.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak;  import java.util.*;  import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class MicroUSB extends altos_device implements AltosDevice { diff --git a/src/Makefile b/src/Makefile index 5bc0a7a0..25e43a0e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -41,13 +41,17 @@ ARMM3DIRS=\  	teledongle-v3.0 teledongle-v3.0/flash-loader \  	teleballoon-v2.0 \  	telebt-v3.0 telebt-v3.0/flash-loader \ +	telebt-v4.0 telebt-v4.0/flash-loader \  	telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \  	telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \  ARMM0DIRS=\  	easymini-v1.0 easymini-v1.0/flash-loader \  	chaoskey-v0.1 chaoskey-v0.1/flash-loader \ -	chaoskey-v1.0 chaoskey-v1.0/flash-loader +	chaoskey-v1.0 chaoskey-v1.0/flash-loader \ +	telemini-v3.0 telemini-v3.0/flash-loader \ +	easymini-v2.0 easymini-v2.0/flash-loader \ +	micropeak-v2.0 micropeak-v2.0/flash-loader  AVRDIRS=\  	telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 08950a97..41d3c1be 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -136,7 +136,7 @@ ISR(USB_GEN_vect)  } -__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; +struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};  /* Walk through the list of descriptors and find a match   */ diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index 7d363c08..259f6512 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -112,7 +112,7 @@ ao_usb_ep0_flush(void)  	USBCS0 = cs0;  } -__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; +__xdata struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};  /* Walk through the list of descriptors and find a match   */ diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index f668fb66..c33aa536 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -126,13 +126,15 @@ struct ao_hmc5883_sample ao_hmc5883_current;  static void  ao_hmc5883(void)  { +	struct ao_hmc5883_sample	sample;  	ao_hmc5883_setup();  	for (;;) { -		ao_hmc5883_sample(&ao_hmc5883_current); -		ao_arch_critical( -			AO_DATA_PRESENT(AO_DATA_HMC5883); -			AO_DATA_WAIT(); -			); +		ao_hmc5883_sample(&sample); +		ao_arch_block_interrupts(); +		ao_hmc5883_current = sample; +		AO_DATA_PRESENT(AO_DATA_HMC5883); +		AO_DATA_WAIT(); +		ao_arch_release_interrupts();  	}  } @@ -141,10 +143,8 @@ static struct ao_task ao_hmc5883_task;  static void  ao_hmc5883_show(void)  { -	struct ao_data	sample; -	ao_data_get(&sample); -	printf ("X: %d Y: %d Z: %d missed irq: %lu\n", -		sample.hmc5883.x, sample.hmc5883.y, sample.hmc5883.z, ao_hmc5883_missed_irq); +	printf ("X: %d Z: %d Y: %d missed irq: %lu\n", +		ao_hmc5883_current.x, ao_hmc5883_current.z, ao_hmc5883_current.y, ao_hmc5883_missed_irq);  }  static const struct ao_cmds ao_hmc5883_cmds[] = { diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 78637b02..b90733df 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -77,7 +77,7 @@  #define HMC5883_ID_C		12  struct ao_hmc5883_sample { -	int16_t		x, y, z; +	int16_t		x, z, y;  };  extern struct ao_hmc5883_sample	ao_hmc5883_current; diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 650407ad..81d3c16c 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -192,7 +192,7 @@ _ao_mpu6000_setup(void)  	_ao_mpu6000_wait_alive();  	/* Reset the whole chip */ -	 +  	_ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1,  			      (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)); @@ -292,7 +292,7 @@ _ao_mpu6000_setup(void)  		ao_delay(AO_MS_TO_TICKS(200));  		_ao_mpu6000_sample(&normal_mode); -	 +  		errors += ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x);  		errors += ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y);  		errors += ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z); @@ -315,7 +315,7 @@ _ao_mpu6000_setup(void)  	/* 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;  } @@ -325,6 +325,7 @@ struct ao_mpu6000_sample	ao_mpu6000_current;  static void  ao_mpu6000(void)  { +	struct ao_mpu6000_sample	sample;  	/* ao_mpu6000_init already grabbed the SPI bus and mutex */  	_ao_mpu6000_setup();  #if AO_MPU6000_SPI @@ -335,14 +336,15 @@ ao_mpu6000(void)  #if AO_MPU6000_SPI  		ao_mpu6000_spi_get();  #endif -		_ao_mpu6000_sample(&ao_mpu6000_current); +		_ao_mpu6000_sample(&sample);  #if AO_MPU6000_SPI  		ao_mpu6000_spi_put(); -#endif	 -		ao_arch_critical( -			AO_DATA_PRESENT(AO_DATA_MPU6000); -			AO_DATA_WAIT(); -			); +#endif +		ao_arch_block_interrupts(); +		ao_mpu6000_current = sample; +		AO_DATA_PRESENT(AO_DATA_MPU6000); +		AO_DATA_WAIT(); +		ao_arch_release_interrupts();  	}  } @@ -351,16 +353,13 @@ static struct ao_task ao_mpu6000_task;  static void  ao_mpu6000_show(void)  { -	struct ao_data	sample; - -	ao_data_get(&sample);  	printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", -		sample.mpu6000.accel_x, -		sample.mpu6000.accel_y, -		sample.mpu6000.accel_z, -		sample.mpu6000.gyro_x, -		sample.mpu6000.gyro_y, -		sample.mpu6000.gyro_z); +		ao_mpu6000_current.accel_x, +		ao_mpu6000_current.accel_y, +		ao_mpu6000_current.accel_z, +		ao_mpu6000_current.gyro_x, +		ao_mpu6000_current.gyro_y, +		ao_mpu6000_current.gyro_z);  }  static const struct ao_cmds ao_mpu6000_cmds[] = { @@ -374,7 +373,7 @@ ao_mpu6000_init(void)  	ao_mpu6000_configured = 0;  	ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); -	 +  #if AO_MPU6000_SPI  	ao_spi_init_cs(AO_MPU6000_SPI_CS_PORT, (1 << AO_MPU6000_SPI_CS_PIN)); @@ -386,7 +385,7 @@ ao_mpu6000_init(void)  	ao_cur_task = &ao_mpu6000_task;  	ao_spi_get(AO_MPU6000_SPI_BUS, AO_SPI_SPEED_1MHz);  	ao_cur_task = NULL; -#endif	 +#endif  	ao_cmd_register(&ao_mpu6000_cmds[0]);  } diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 261df67f..914e0c1b 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -191,17 +191,23 @@ ao_ms5607_sample(__xdata struct ao_ms5607_sample *sample)  #include "ao_ms5607_convert.c"  #endif -#if HAS_TASK +#ifndef HAS_MS5607_TASK +#define HAS_MS5607_TASK HAS_TASK +#endif +  __xdata struct ao_ms5607_sample	ao_ms5607_current; +#if HAS_MS5607_TASK  static void  ao_ms5607(void)  { +	struct ao_ms5607_sample	sample;  	ao_ms5607_setup();  	for (;;)  	{ -		ao_ms5607_sample(&ao_ms5607_current); +		ao_ms5607_sample(&sample);  		ao_arch_block_interrupts(); +		ao_ms5607_current = sample;  		AO_DATA_PRESENT(AO_DATA_MS5607);  		AO_DATA_WAIT();  		ao_arch_release_interrupts(); @@ -209,7 +215,9 @@ ao_ms5607(void)  }  __xdata struct ao_task ao_ms5607_task; +#endif +#if HAS_TASK  void  ao_ms5607_info(void)  { @@ -248,6 +256,8 @@ ao_ms5607_init(void)  #if HAS_TASK  	ao_cmd_register(&ao_ms5607_cmds[0]); +#endif +#if HAS_MS5607_TASK  	ao_add_task(&ao_ms5607_task, ao_ms5607, "ms5607");  #endif diff --git a/src/drivers/ao_rn4678.c b/src/drivers/ao_rn4678.c new file mode 100644 index 00000000..98dc35b5 --- /dev/null +++ b/src/drivers/ao_rn4678.c @@ -0,0 +1,606 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +#include <ao.h> +#include <ao_rn4678.h> +#include <ao_exti.h> +#include <stdarg.h> + +static uint8_t	ao_rn_connected; + +#define AO_RN_DEBUG 0 + +#if AO_RN_DEBUG +static void ao_rn_dbg(char *format, ...) { +	va_list a; +	uint32_t	irq = ao_arch_irqsave(); +	ao_arch_release_interrupts(); +	va_start(a, format); +	vprintf(format, a); +	va_end(a); +	flush(); +	ao_arch_irqrestore(irq); +} + +static char	ao_rn_dir; + +static void +ao_rn_log_char(char c, char dir) +{ +	if (dir != ao_rn_dir) { +		putchar(dir); putchar('\n'); +		ao_rn_dir = dir; +	} +	switch (c) { +	case '\r': +		putchar('\\'); putchar('r'); +		break; +	case '\n': +		putchar('\\'); putchar('n'); +		break; +	default: +		putchar(c); +	} +	flush(); +} + +static void +ao_rn_log_out_char(char c) +{ +	ao_rn_log_char(c, '}'); +} + +static void +ao_rn_log_in_char(char c) +{ +	ao_rn_log_char(c, '{'); +} + +static inline void +ao_rn_putchar(char c) +{ +	ao_rn_log_out_char(c); +	ao_serial_rn_putchar(c); +} + +static inline int +_ao_rn_pollchar(void) +{ +	int	c = _ao_serial_rn_pollchar(); + +	if (c != AO_READ_AGAIN) { +		ao_arch_release_interrupts(); +		ao_rn_log_in_char((char) c); +		ao_arch_block_interrupts(); +	} +	return c; +} +#else +#define ao_rn_dbg(fmt, ...) +#define ao_rn_putchar(c)	ao_serial_rn_putchar(c) +#define _ao_rn_pollchar()	_ao_serial_rn_pollchar() +#endif + +/* For stdio, this skips all status messages *sigh* */ + +#define STATUS_CHAR	'%' + +static const char *status_strings[] = { +	"RFCOMM_CLOSE", +	"RFCOMM_OPEN", +	"CONNECT", +	"LCONNECT", +	"DISCONN", +	"BONDED", +}; + +#define NUM_STATUS_STRING	(sizeof status_strings/sizeof status_strings[0]) + +static char		ao_rn_buffer[64]; +static int		ao_rn_buf_cnt, ao_rn_buf_ptr; +static int		ao_rn_draining; +static AO_TICK_TYPE	ao_rn_buf_time; + +/* Well, this is annoying. The status strings from the RN4678 can't be + * disabled due to a firmware bug. So, this code finds those in the + * input and strips them out. + */ +int +_ao_wrap_rn_pollchar(void) +{ +	int		c = AO_READ_AGAIN; +	unsigned	i; +	int		done = 0; + +	while (!done && !ao_rn_draining) { +		c = _ao_serial_rn_pollchar(); + +		if (c == AO_READ_AGAIN) { +			if (ao_rn_buf_cnt && (ao_time() - ao_rn_buf_time) > AO_MS_TO_TICKS(1000)) { +				ao_rn_draining = 1; +				continue; +			} +			return AO_READ_AGAIN; +		} + +		if (ao_rn_buf_cnt) { +			/* buffering chars */ + +			if (c == STATUS_CHAR) { +				/* End of status string, drop it and carry on */ +				ao_rn_buffer[ao_rn_buf_cnt] = '\0'; +//				ao_rn_dbg("discard %s\n", ao_rn_buffer); +				ao_rn_buf_cnt = 0; +			} else if (ao_rn_buf_cnt == sizeof(ao_rn_buffer)) { +				/* If we filled the buffer, just give up */ +				ao_rn_draining = 1; +			} else { +				ao_rn_buffer[ao_rn_buf_cnt++] = c; +				for (i = 0; i < NUM_STATUS_STRING; i++) { +					int cmp = strlen(status_strings[i]); +					if (cmp >= ao_rn_buf_cnt) +						cmp = ao_rn_buf_cnt-1; +					if (memcmp(ao_rn_buffer+1, status_strings[i], cmp) == 0) +						break; +				} +				if (i == NUM_STATUS_STRING) +					ao_rn_draining = 1; +			} +		} else if (c == STATUS_CHAR) { +			ao_rn_buffer[0] = c; +			ao_rn_buf_cnt = 1; +			ao_rn_buf_ptr = 0; +			ao_rn_buf_time = ao_time(); +		} else +			done = 1; +	} +	if (ao_rn_draining) { +		c = ao_rn_buffer[ao_rn_buf_ptr++] & 0xff; +		if (ao_rn_buf_ptr == ao_rn_buf_cnt) { +			ao_rn_buf_ptr = ao_rn_buf_cnt = 0; +			ao_rn_draining = 0; +		} +	} +	return c; +} + +static void +ao_rn_puts(char *s) +{ +	char c; + +	while ((c = *s++)) +		ao_rn_putchar(c); +} + +static void +ao_rn_drain(void) +{ +	int	timeout = 0; + +//	ao_rn_dbg("drain...\n"); +	ao_serial_rn_drain(); +	while (!timeout) { +		ao_arch_block_interrupts(); +		while (_ao_rn_pollchar() == AO_READ_AGAIN) { +			if (_ao_serial_rn_sleep_for(AO_MS_TO_TICKS(10))) { +				timeout = 1; +				break; +			} +		} +		ao_arch_release_interrupts(); +	} +//	ao_rn_dbg("drain done\n"); +} + +static void +ao_rn_send_cmd(char *cmd, char *param) +{ +//	ao_rn_dbg("send_cmd %s%s\n", cmd, param ? param : ""); +	ao_rn_drain(); +	ao_rn_puts(cmd); +	if (param) +		ao_rn_puts(param); +	ao_rn_putchar('\r'); +} + +static int +ao_rn_wait_char(AO_TICK_TYPE giveup_time) +{ +	int c; + +	ao_arch_block_interrupts(); +	while ((c = _ao_rn_pollchar()) == AO_READ_AGAIN) { +		AO_TICK_SIGNED	delay = (AO_TICK_SIGNED) (giveup_time - ao_time()); +		if (delay < 0) { +			ao_arch_release_interrupts(); +			return AO_READ_AGAIN; +		} +		_ao_serial_rn_sleep_for(delay); +	} +	ao_arch_release_interrupts(); +	return c; +} + +static int +ao_rn_wait_for(int timeout, char *match) +{ +	char		reply[AO_RN_MAX_REPLY_LEN + 1]; +	int		match_len = strlen(match); +	AO_TICK_TYPE	giveup_time = ao_time() + timeout; +	int		c; + +//	ao_rn_dbg("wait for %d, \"%s\"\n", timeout, match); +	memset(reply, ' ', sizeof(reply)); +	while (memcmp(reply, match, match_len) != 0) { +		c = ao_rn_wait_char(giveup_time); +		if (c == AO_READ_AGAIN) { +//			ao_rn_dbg("\twait for timeout\n"); +			return AO_RN_TIMEOUT; +		} +		reply[match_len] = (char) c; +		memmove(reply, reply+1, match_len); +		reply[match_len] = '\0'; +//		ao_rn_dbg("\tmatch now \"%s\"\n", reply); +	} +//	ao_rn_dbg("\twait for ok\n"); +	return AO_RN_OK; +} + +static int +ao_rn_wait_line(AO_TICK_TYPE giveup_time, char *line, int len) +{ +	char *l = line; + +//	ao_rn_dbg("wait line\n"); +	for (;;) { +		int c = ao_rn_wait_char(giveup_time); + +		/* timeout */ +		if (c == AO_READ_AGAIN) { +//			ao_rn_dbg("\twait line timeout\n"); +			return AO_RN_TIMEOUT; +		} + +		/* done */ +		if (c == '\r') { +			*l = '\0'; +//			ao_rn_dbg("\twait line \"%s\"\n", line); +			return AO_RN_OK; +		} + +		if (c == '\n') +			continue; + +		/* buffer overrun */ +		if (len <= 1) +			return AO_RN_ERROR; + +		*l++ = (char) c; +		len--; +	} +} + +static int +ao_rn_wait_status(void) +{ +	char		message[AO_RN_MAX_REPLY_LEN]; +	AO_TICK_TYPE	giveup_time = ao_time() + AO_RN_CMD_TIMEOUT; +	int		status; + +//	ao_rn_dbg("wait status\n"); +	status = ao_rn_wait_line(giveup_time, message, sizeof (message)); +	if (status == AO_RN_OK) +		if (strncmp(message, "AOK", 3) != 0) +			status = AO_RN_ERROR; +	return status; +} + +static int +ao_rn_set_name(void) +{ +	char	sn[8]; +	char	*s = sn + 8; +	int	n; + +//	ao_rn_dbg("set name...\n"); +	*--s = '\0'; +	n = ao_serial_number; +	do { +		*--s = '0' + n % 10; +	} while (n /= 10); +	ao_rn_send_cmd(AO_RN_SET_NAME_CMD "TeleBT-", s); +	return ao_rn_wait_status(); +} + +static int +ao_rn_get_name(char *name, int len) +{ +//	ao_rn_dbg("get name...\n"); +	ao_rn_send_cmd(AO_RN_GET_NAME_CMD, NULL); +	return ao_rn_wait_line(ao_time() + AO_RN_CMD_TIMEOUT, name, len); +} + +static void +ao_rn_check_link(void) +{ +	ao_rn_connected = 1 - ao_gpio_get(AO_RN_CONNECTED_PORT, AO_RN_CONNECTED_PIN, foo); +} + +static void +ao_rn_isr(void) +{ +	ao_rn_check_link(); +	ao_wakeup(&ao_rn_connected); +} + +static void +ao_bt_panic(int where) +{ +	int i; +	for (;;) { +		for (i = 0; i < 50; i++) { +			ao_led_toggle(AO_BT_LED); +			ao_delay(AO_MS_TO_TICKS(10)); +		} +		ao_led_off(AO_BT_LED); +		ao_delay(AO_MS_TO_TICKS(500)); +		for (i = 0; i < where; i++) { +			ao_led_for(AO_BT_LED, AO_MS_TO_TICKS(200)); +			ao_delay(AO_MS_TO_TICKS(200)); +		} +	} +} + +static uint8_t	ao_rn_stdio; + +/* + * Set the stdio echo for the bluetooth link + */ +void +ao_rn_echo(uint8_t echo) +{ +	ao_stdios[ao_rn_stdio].echo = echo; +} + +static void +ao_rn(void) +{ +	int	status = AO_RN_ERROR; +	char	name[17]; +	int	i; + +	ao_rn_dbg("ao_rn top\n"); + +	/* Select CMD mode after the device gets out of reset */ +	ao_gpio_set(AO_RN_CMD_PORT, AO_RN_CMD_PIN, foo, AO_RN_CMD_CMD); + +	for (i = 0; i < 3; i++) { +		ao_rn_dbg("reset device\n"); + +		ao_gpio_set(AO_RN_RST_N_PORT, AO_RN_RST_N_PIN, foo, 0); +		ao_delay(AO_MS_TO_TICKS(100)); + +		/* Reboot the RN4678 and wait for it to start talking */ +		ao_rn_drain(); +		ao_gpio_set(AO_RN_RST_N_PORT, AO_RN_RST_N_PIN, foo, 1); +		status = ao_rn_wait_for(AO_RN_REBOOT_TIMEOUT, AO_RN_REBOOT_MSG); +		if (status != AO_RN_OK) { +			ao_rn_dbg("reboot failed\n"); +			continue; +		} + +		/* After it reboots, it can take a moment before it responds +		 * to commands +		 */ +		status = ao_rn_wait_for(AO_RN_REBOOT_TIMEOUT, "CMD> "); + +		if (status == AO_RN_TIMEOUT) { +			ao_rn_puts("$$$"); +			(void) ao_rn_wait_for(AO_RN_REBOOT_TIMEOUT, "CMD> "); +		} + +		ao_rn_send_cmd(AO_RN_VERSION_CMD, NULL); +		(void) ao_rn_wait_status(); + +		/* Check to see if the name is already set and assume +		 * that the device is ready to go +		 */ +		status = ao_rn_get_name(name, sizeof (name)); +		if (status != AO_RN_OK) { +			ao_rn_dbg("get name failed\n"); +			status = ao_rn_get_name(name, sizeof (name)); +			if (status != AO_RN_OK) +				continue; +		} + +		if (strncmp(name, "TeleBT-", 7) == 0) { +			ao_rn_dbg("name is set\n"); +			status = AO_RN_OK; +			break; +		} + +		/* Make the command pin control command/data mode */ +		ao_rn_send_cmd(AO_RN_SET_COMMAND_PIN, NULL); +		if (ao_rn_wait_status() != AO_RN_OK) { +			ao_rn_dbg("set command pin failed\n"); +			continue; +		} + +		ao_rn_send_cmd(AO_RN_SET_STATUS_STRING, AO_RN_STATUS_STRING_ENABLE); +		if (ao_rn_wait_status() != AO_RN_OK) { +			ao_rn_dbg("set status string\n"); +			continue; +		} + +		/* Select 'fast' mode to ignore command sequence (more or less) */ +		ao_rn_send_cmd(AO_RN_SET_FAST_MODE, NULL); +		if (ao_rn_wait_status() != AO_RN_OK) { +			ao_rn_dbg("set fast mode failed\n"); +			continue; +		} + +		/* Finally, set the name. Doing this last makes it possible to check +		 * if the whole sequence has been done +		 */ +		if (ao_rn_set_name() != AO_RN_OK) { +			ao_rn_dbg("set name failed\n"); +			continue; +		} + +		/* After we've configured the device, go back around and reboot it +		 * as that's how we get the new configuration to take effect +		 */ +	} +	ao_rn_dbg("ao_rn status %d\n", status); + +	if (status != AO_RN_OK) +		ao_bt_panic(4); + +	ao_gpio_set(AO_RN_CMD_PORT, AO_RN_CMD_PIN, foo, AO_RN_CMD_DATA); + +	/* Wait for the hardware to finish sending messages, then clear the queue */ +	ao_delay(AO_MS_TO_TICKS(200)); +	ao_rn_drain(); + +	ao_exti_enable(AO_RN_CONNECTED_PORT, AO_RN_CONNECTED_PIN); + +#if AO_RN_DEBUG + +	/* +	 * Separate debug code when things aren't working. Just dump +	 * inbound bluetooth characters to stdout +	 */ +	for (;;) { +		int	c; + +		ao_arch_block_interrupts(); +		while ((c = _ao_rn_pollchar()) == AO_READ_AGAIN) +			ao_sleep(&ao_serial_rn_rx_fifo); +		ao_arch_release_interrupts(); +	} +#else +	ao_rn_stdio = ao_add_stdio(_ao_wrap_rn_pollchar, +				   ao_serial_rn_putchar, +				   NULL); + +	ao_rn_echo(0); +	ao_rn_check_link(); +	/* +	 * Now just hang around and flash the blue LED when we've got +	 * a connection +	 */ +	for (;;) { +		ao_arch_block_interrupts(); +		while (!ao_rn_connected) +			ao_sleep(&ao_rn_connected); +		ao_arch_release_interrupts(); +		while (ao_rn_connected) { +			ao_led_for(AO_BT_LED, AO_MS_TO_TICKS(20)); +			if (ao_rn_buf_cnt != 0) +				ao_wakeup(&ao_stdin_ready); +			ao_delay(AO_SEC_TO_TICKS(3)); +		} +	} +#endif +} + +static struct ao_task ao_rn_task; + +static void +ao_rn_factory(void) +{ +	int	i; +	int	v = 0; + +	/* +	 * Factory reset. Flip pin P3_1 5 times within the first five +	 * seconds of power-on +	 */ + +	/* Select our target output pin */ +	ao_enable_output(AO_RN_P3_1_PORT, AO_RN_P3_1_PIN, foo, v); + +	/* Turn off the BT device using the SW_BTN pin */ +	printf("Power down BT\n"); flush(); +	ao_gpio_set(AO_RN_SW_BTN_PORT, AO_RN_SW_BTN_PIN, foo, 0); +	ao_delay(AO_MS_TO_TICKS(1000)); + +	/* And turn it back on */ +	printf("Power up BT\n"); flush(); +	ao_gpio_set(AO_RN_SW_BTN_PORT, AO_RN_SW_BTN_PIN, foo, 1); + +	/* Right after power on, poke P3_1 five times to force a +	 * factory reset +	 */ +	for (i = 0; i < 20; i++) { +		v = 1-v; +		ao_delay(AO_MS_TO_TICKS(50)); +		ao_gpio_set(AO_RN_P3_1_PORT, AO_RN_P3_1_PIN, foo, v); +		ao_led_toggle(AO_BT_LED); +	} + +	/* And let P3_1 float again */ +	ao_enable_input(AO_RN_P3_1_PORT, AO_RN_P3_1_PIN, AO_EXTI_MODE_PULL_NONE); + +	printf("Reboot BT\n"); flush(); +	ao_delay(AO_MS_TO_TICKS(100)); +	ao_gpio_set(AO_RN_RST_N_PORT, AO_RN_RST_N_PIN, foo, 0); +	ao_delay(AO_MS_TO_TICKS(100)); +	ao_gpio_set(AO_RN_RST_N_PORT, AO_RN_RST_N_PIN, foo, 1); +} + +#if AO_RN_DEBUG +static void +ao_rn_send(void) +{ +	int	c; + +	while ((c = getchar()) != '~') +		ao_rn_putchar(c); +} +#endif + +static const struct ao_cmds rn_cmds[] = { +	{ ao_rn_factory, "F\0Factory reset rn4678" }, +#if AO_RN_DEBUG +	{ ao_rn_send, "B\0Send data to rn4678. End with ~" }, +#endif +	{ 0 }, +}; + +void +ao_rn4678_init(void) +{ +	(void) ao_rn_set_name; + +	ao_serial_rn_set_speed(AO_SERIAL_SPEED_115200); + +	/* Reset line */ +	ao_enable_output(AO_RN_RST_N_PORT, AO_RN_RST_N_PIN, foo, 0); + +	/* SW_BTN */ +	ao_enable_output(AO_RN_SW_BTN_PORT, AO_RN_SW_BTN_PIN, foo, 1); + +	/* P3_7 command/data selector */ +	ao_enable_output(AO_RN_CMD_PORT, AO_RN_CMD_PIN, foo, AO_RN_CMD_CMD); + +	ao_enable_input(AO_RN_CONNECTED_PORT, AO_RN_CONNECTED_PIN, AO_EXTI_MODE_PULL_NONE); +	ao_exti_setup(AO_RN_CONNECTED_PORT, AO_RN_CONNECTED_PIN, +		      AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_LOW, +		      ao_rn_isr); + +	ao_cmd_register(rn_cmds); +	ao_add_task(&ao_rn_task, ao_rn, "bluetooth"); +} diff --git a/src/drivers/ao_rn4678.h b/src/drivers/ao_rn4678.h new file mode 100644 index 00000000..a4dcea38 --- /dev/null +++ b/src/drivers/ao_rn4678.h @@ -0,0 +1,101 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +#ifndef _AO_RN4678_H_ +#define _AO_RN4678_H_ + +/* From the rn4678 pictail board + +    1	SW_BTN	0-off/1-on	 2	P2_0	1-app/0-test (boot time) +    3	P2_4	1-app/0-WF	 4	EAN	0-app/1-WF (reboots) +    5				 6	RTS	0 +    7				 8	P3_2	1 (NC) +    9	TXD			10	P3_3	1 (NC) +   11	RXD			12	P3_4	1 (NC) +   13				14 +   15				16	P3_7	1 (NC) +   17	P0_5	1 (NC)		18	RST_N	1 run/0 reset +   19	WAKE_UP	1 run/0 btn	20 +   21	P0_4	0 (NC)		22 +   23	P1_5	1 (NC)		24	P3_1	1 (NC) +   25	CTS	0		26	3.3V +   27				28	GND + + +   Interesting pins: + +   Not connected to microcontroller: + +   SW_BTN	0-off		1-on +   P2_4		0 write-flash	1-app +   WAKE_UP	0-stop		1-run +   P2_0		0 test		1-run +   EAN		1-WF (reboots)	0-run +   RST_N	0 reset		1 run + +   Connected to microcontroller: + +   CTS		mostly 0 +   RTS		mostly 1 + +   TXD +   RXD + +   Other connections -- LDO33_O to VDD_IO + +*/ + +#define AO_RN_REBOOT_MSG	"REBOOT" + +#define AO_RN_CMD_TIMEOUT	AO_MS_TO_TICKS(200) + +#define AO_RN_REBOOT_TIMEOUT	AO_MS_TO_TICKS(2000) + +#define AO_RN_MAX_REPLY_LEN	10 + +#define AO_RN_SET_NAME_CMD		"SN," +#define AO_RN_GET_NAME_CMD		"GN" + +#define AO_RN_SET_STATUS_STRING	"so," +#define AO_RN_STATUS_STRING_DISABLE	" " +#define AO_RN_STATUS_STRING_ENABLE	"%,%" + +#define AO_RN_REBOOT_CMD		"R,1" + +#define AO_RN_VERSION_CMD		"V" + +#define AO_RN_TIMEOUT	-1 +#define AO_RN_ERROR	0 +#define AO_RN_OK	1 + +#define AO_RN_SET_COMMAND_PIN	"SX,07,0B" + +#define AO_RN_SET_AUTH_JUST_WORKS	"SA,2" +#define AO_RN_SET_FAST_MODE		"SQ,9000" + +/* This pin is configured to control cmd/data mode */ +#define AO_RN_CMD_PORT	AO_RN_P3_7_PORT +#define AO_RN_CMD_PIN	AO_RN_P3_7_PIN + +#define AO_RN_CMD_CMD	0 +#define AO_RN_CMD_DATA	1 + +/* This pin indicates BT connection status */ +#define AO_RN_CONNECTED_PORT	AO_RN_P1_5_PORT +#define AO_RN_CONNECTED_PIN	AO_RN_P1_5_PIN + +void +ao_rn4678_init(void); + +#endif /* _AO_RN_H_ */ diff --git a/src/easymini-v1.0/ao_pins.h b/src/easymini-v1.0/ao_pins.h index 5983bb9e..45c6891d 100644 --- a/src/easymini-v1.0/ao_pins.h +++ b/src/easymini-v1.0/ao_pins.h @@ -42,7 +42,7 @@  #define PACKET_HAS_SLAVE	0 -#define AO_LOG_FORMAT		AO_LOG_FORMAT_EASYMINI +#define AO_LOG_FORMAT		AO_LOG_FORMAT_EASYMINI1  /* USART */ diff --git a/src/easymini-v2.0/.gitignore b/src/easymini-v2.0/.gitignore new file mode 100644 index 00000000..e5f7d586 --- /dev/null +++ b/src/easymini-v2.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +*.elf diff --git a/src/easymini-v2.0/Makefile b/src/easymini-v2.0/Makefile new file mode 100644 index 00000000..9b4cc6d7 --- /dev/null +++ b/src/easymini-v2.0/Makefile @@ -0,0 +1,83 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_pins.h \ +	ao_product.h \ +	stm32f0.h + +# +# Common AltOS sources +# + +ALTOS_SRC = \ +	ao_interrupt.c \ +	ao_boot_chain.c \ +	ao_romconfig.c \ +	ao_product.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_stdio.c \ +	ao_storage.c \ +	ao_report.c \ +	ao_ignite.c \ +	ao_flight.c \ +	ao_kalman.c \ +	ao_sample.c \ +	ao_data.c \ +	ao_convert_pa.c \ +	ao_convert_volt.c \ +	ao_task.c \ +	ao_log.c \ +	ao_log_mini.c \ +	ao_cmd.c \ +	ao_config.c \ +	ao_dma_stm.c \ +	ao_timer.c \ +	ao_exti_stm.c \ +	ao_spi_stm.c \ +	ao_adc_stm.c \ +	ao_usb_stm.c \ +	ao_m25.c \ +	ao_ms5607.c \ +	ao_beep_stm.c + +PRODUCT=EasyMini-v2.0 +PRODUCT_DEF=-DEASYMINI_V_2_0 +IDPRODUCT=0x0026 + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os + +PROGNAME=easymini-v2.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_easymini.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/easymini-v2.0/ao_easymini.c b/src/easymini-v2.0/ao_easymini.c new file mode 100644 index 00000000..7246cae2 --- /dev/null +++ b/src/easymini-v2.0/ao_easymini.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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 <ao.h> +#include <ao_exti.h> + +void +main(void) +{ +	ao_clock_init(); +	ao_task_init(); +	ao_timer_init(); + +	ao_dma_init(); +	ao_spi_init(); +	ao_exti_init(); + +	ao_adc_init(); + +#if HAS_BEEP +	ao_beep_init(); +#endif +#if HAS_USB +	ao_usb_init(); +#endif +	ao_cmd_init(); + +	ao_ms5607_init(); + +	ao_storage_init(); +	ao_flight_init(); +	ao_log_init(); +	ao_report_init(); +	ao_igniter_init(); +	ao_config_init(); + +	ao_start_scheduler(); +} diff --git a/src/easymini-v2.0/ao_pins.h b/src/easymini-v2.0/ao_pins.h new file mode 100644 index 00000000..2ec0e90b --- /dev/null +++ b/src/easymini-v2.0/ao_pins.h @@ -0,0 +1,163 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define HAS_BEEP		1 +#define HAS_BATTERY_REPORT	1 + +#define AO_STACK_SIZE	448 + +#define IS_FLASH_LOADER	0 + +/* 48MHz clock based on 16MHz reference */ +//#define AO_HSI48	1 +#define AO_HSE			16000000 +#define AO_RCC_CFGR_PLLMUL	STM_RCC_CFGR_PLLMUL_3 +#define AO_RCC_CFGR2_PLLDIV	STM_RCC_CFGR2_PREDIV_1 +#define AO_PLLMUL		3 +#define AO_PLLDIV		1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 40MHz */ +#define AO_APB_PRESCALER	1 +#define AO_RCC_CFGR_PPRE_DIV	STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB			1 +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	1 +#define AO_USB_FORCE_IDLE	1 + +#define AO_LOG_FORMAT		AO_LOG_FORMAT_EASYMINI2 + +#define HAS_BOOT_RADIO		0 + +#define HAS_ACCEL		0 +#define HAS_GPS			0 +#define HAS_RADIO		0 +#define HAS_FLIGHT		1 +#define HAS_EEPROM		1 +#define HAS_TELEMETRY		0 +#define HAS_APRS		0 +#define HAS_LOG			1 +#define USE_INTERNAL_FLASH	0 +#define HAS_IGNITE		1 +#define HAS_IGNITE_REPORT	1 + +/* Beeper is on Tim3 CH3 */ +#define BEEPER_TIMER		3 +#define BEEPER_CHANNEL		3 +#define BEEPER_PORT		(&stm_gpiob) +#define BEEPER_PIN		0 +#define BEEPER_AFR		STM_AFR_AF1 + +/* SPI */ + +#define HAS_SPI_1		1 +#define SPI_1_PA5_PA6_PA7	1 +#define SPI_1_PB3_PB4_PB5	1 +#define SPI_1_OSPEEDR		STM_OSPEEDR_MEDIUM + +/* M25 */ + +#define M25_MAX_CHIPS		1 +#define AO_M25_SPI_CS_PORT	(&stm_gpioa) +#define AO_M25_SPI_CS_MASK	(1 << 15) +#define AO_M25_SPI_BUS		AO_SPI_1_PB3_PB4_PB5 + +/* MS5607 */ + +#define HAS_MS5607		1 +#define HAS_MS5611		0 +#define AO_MS5607_PRIVATE_PINS	1 +#define AO_MS5607_CS_PORT	(&stm_gpioa) +#define AO_MS5607_CS_PIN	4 +#define AO_MS5607_CS_MASK	(1 << AO_MS5607_CS_PIN) +#define AO_MS5607_MISO_PORT	(&stm_gpioa) +#define AO_MS5607_MISO_PIN	6 +#define AO_MS5607_MISO_MASK	(1 << AO_MS5607_MISO_PIN) +#define AO_MS5607_SPI_INDEX	AO_SPI_1_PA5_PA6_PA7 +#define AO_MS5607_SPI_SPEED	AO_SPI_SPEED_12MHz + +#define AO_DATA_RING		64 + +/* + * ADC + */ + +#define HAS_ADC			1 + +#define AO_ADC_PIN0_PORT	(&stm_gpioa)	/* sense_m */ +#define AO_ADC_PIN0_PIN		0 +#define AO_ADC_PIN0_CH		0 +#define AO_ADC_PIN1_PORT	(&stm_gpioa)	/* sense_a */ +#define AO_ADC_PIN1_PIN		1 +#define AO_ADC_PIN1_CH		1 +#define AO_ADC_PIN2_PORT	(&stm_gpioa)	/* v_batt */ +#define AO_ADC_PIN2_PIN		2 +#define AO_ADC_PIN2_CH		2 + +#define AO_ADC_RCC_AHBENR	((1 << STM_RCC_AHBENR_IOPAEN)) + +#define AO_NUM_ADC		3 + +struct ao_adc { +	int16_t		sense_m; +	int16_t		sense_a; +	int16_t		v_batt; +}; + +/* + * Igniter + */ + +#define AO_IGNITER_CLOSED	400 +#define AO_IGNITER_OPEN		60 + +#define AO_IGNITER_DROGUE_PORT	(&stm_gpiob) +#define AO_IGNITER_DROGUE_PIN	6 +#define AO_IGNITER_SET_DROGUE(v)	ao_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, v) + +#define AO_IGNITER_MAIN_PORT	(&stm_gpiob) +#define AO_IGNITER_MAIN_PIN	7 +#define AO_IGNITER_SET_MAIN(v)	ao_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, v) + +#define AO_SENSE_DROGUE(p)	((p)->adc.sense_a) +#define AO_SENSE_MAIN(p)	((p)->adc.sense_m) + +#define AO_ADC_DUMP(p) \ +	printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ +	       (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) + +/* + * Voltage divider on ADC battery sampler + */ +#define AO_BATTERY_DIV_PLUS	100	/* 100k */ +#define AO_BATTERY_DIV_MINUS	27	/* 27k */ + +/* + * Voltage divider on ADC igniter samplers + */ +#define AO_IGNITE_DIV_PLUS	100	/* 100k */ +#define AO_IGNITE_DIV_MINUS	27	/* 27k */ + +/* + * ADC reference in decivolts + */ +#define AO_ADC_REFERENCE_DV	33 diff --git a/src/easymini-v2.0/flash-loader/.gitignore b/src/easymini-v2.0/flash-loader/.gitignore new file mode 100644 index 00000000..a8a0dcec --- /dev/null +++ b/src/easymini-v2.0/flash-loader/.gitignore @@ -0,0 +1 @@ +*.bin diff --git a/src/easymini-v2.0/flash-loader/Makefile b/src/easymini-v2.0/flash-loader/Makefile new file mode 100644 index 00000000..8a611751 --- /dev/null +++ b/src/easymini-v2.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=easymini-v2.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/altoslib/AltosStateIterable.java b/src/easymini-v2.0/flash-loader/ao_pins.h index 5332aecd..3098fc22 100644 --- a/altoslib/AltosStateIterable.java +++ b/src/easymini-v2.0/flash-loader/ao_pins.h @@ -16,28 +16,22 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ -import java.io.*; -import java.util.*; +#include <ao_flash_stm_pins.h> -public abstract class AltosStateIterable implements Iterable<AltosState> { +/* pin 5 (PB1) on debug header to gnd for boot mode */ -	public void write_comments (PrintStream out) { -	} +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpiob +#define AO_BOOT_APPLICATION_PIN		1 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP -	public abstract void write(PrintStream out); +/* USB */ +#define HAS_USB			1 +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	1 -	public static AltosStateIterable iterable(File file) { -		FileInputStream in; -		try { -			in = new FileInputStream(file); -		} catch (Exception e) { -			return null; -		} -		if (file.getName().endsWith("telem")) -			return new AltosTelemetryFile(in); -		else -			return new AltosEepromFile(in); -	} -} +#endif /* _AO_PINS_H_ */ diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 5dda1c85..25634ffc 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -35,6 +35,10 @@ __pdata uint8_t ao_config_loaded;  __pdata uint8_t ao_config_dirty;  __xdata uint8_t ao_config_mutex; +#if HAS_FORCE_FREQ +__xdata uint8_t ao_force_freq; +#endif +  #ifndef AO_CONFIG_DEFAULT_APRS_INTERVAL  #define AO_CONFIG_DEFAULT_APRS_INTERVAL	0  #endif diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index a2f2c6ca..aca669db 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -45,7 +45,7 @@ extern __pdata enum ao_flight_state ao_log_state;  #define AO_LOG_FORMAT_TELEMETRY		3	/* 32 byte ao_telemetry records */  #define AO_LOG_FORMAT_TELESCIENCE	4	/* 32 byte typed telescience records */  #define AO_LOG_FORMAT_TELEMEGA_OLD	5	/* 32 byte typed telemega records */ -#define AO_LOG_FORMAT_EASYMINI		6	/* 16-byte MS5607 baro only, 3.0V supply */ +#define AO_LOG_FORMAT_EASYMINI1		6	/* 16-byte MS5607 baro only, 3.0V supply */  #define AO_LOG_FORMAT_TELEMETRUM	7	/* 16-byte typed telemetrum records */  #define AO_LOG_FORMAT_TELEMINI2		8	/* 16-byte MS5607 baro only, 3.3V supply, cc1111 SoC */  #define AO_LOG_FORMAT_TELEGPS		9	/* 32 byte telegps records */ @@ -53,6 +53,7 @@ extern __pdata enum ao_flight_state ao_log_state;  #define AO_LOG_FORMAT_DETHERM		11	/* 16-byte MS5607 baro only, no ADC */  #define AO_LOG_FORMAT_TELEMINI3		12	/* 16-byte MS5607 baro only, 3.3V supply, stm32f042 SoC */  #define AO_LOG_FORMAT_TELEFIRETWO	13	/* 32-byte test stand data */ +#define AO_LOG_FORMAT_EASYMINI2		14	/* 16-byte MS5607 baro only, 3.3V supply, stm32f042 SoC */  #define AO_LOG_FORMAT_NONE		127	/* No log at all */  extern __code uint8_t ao_log_format; @@ -252,8 +253,8 @@ struct ao_log_mega {  			int16_t		gyro_y;		/* 20 */  			int16_t		gyro_z;		/* 22 */  			int16_t		mag_x;		/* 24 */ -			int16_t		mag_y;		/* 26 */ -			int16_t		mag_z;		/* 28 */ +			int16_t		mag_z;		/* 26 */ +			int16_t		mag_y;		/* 28 */  			int16_t		accel;		/* 30 */  		} sensor;	/* 32 */  		/* AO_LOG_TEMP_VOLT */ @@ -309,9 +310,7 @@ struct ao_log_firetwo {  		/* AO_LOG_FLIGHT */  		struct {  			uint16_t	flight;		/* 4 */ -			uint16_t	idle_pressure;	/* 6 */ -			uint16_t	idle_thrust;	/* 8 */ -		} flight;	/* 16 */ +		} flight;	/* 6 */  		/* AO_LOG_STATE */  		struct {  			uint16_t	state;		/* 4 */ diff --git a/src/kernel/ao_log_firetwo.c b/src/kernel/ao_log_fireone.c index 4b42abe4..1a82673d 100644 --- a/src/kernel/ao_log_firetwo.c +++ b/src/kernel/ao_log_fireone.c @@ -75,8 +75,6 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_firetwo))] ;  void  ao_log(void)  { -	uint16_t ao_idle_pressure = 0;		// write code to capture pre-test values someday -	uint16_t ao_idle_thrust = 0;  	uint16_t ao_flight_state = ao_flight_startup;  	ao_storage_setup(); @@ -89,8 +87,6 @@ ao_log(void)  		log.type = AO_LOG_FLIGHT;  		log.tick = ao_time(); -		log.u.flight.idle_pressure = ao_idle_pressure; -		log.u.flight.idle_thrust = ao_idle_thrust;  		log.u.flight.flight = ao_flight_number;  		ao_log_firetwo(&log); diff --git a/src/kernel/ao_log_mega.c b/src/kernel/ao_log_mega.c index a0212198..b86abe7a 100644 --- a/src/kernel/ao_log_mega.c +++ b/src/kernel/ao_log_mega.c @@ -135,8 +135,8 @@ ao_log(void)  #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.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y;  #endif  				log.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]);  				ao_log_mega(&log); diff --git a/src/kernel/ao_log_micro.c b/src/kernel/ao_log_micro.c index aa0f5c76..d6f9c5a8 100644 --- a/src/kernel/ao_log_micro.c +++ b/src/kernel/ao_log_micro.c @@ -19,7 +19,12 @@  #include <ao.h>  #include <ao_micropeak.h>  #include <ao_log_micro.h> +#ifndef ao_async_byte  #include <ao_async.h> +#else +#include <ao_serial.h> +#endif +#include <ao_storage.h>  static uint16_t ao_log_offset = STARTING_LOG_OFFSET; diff --git a/src/kernel/ao_log_micro.h b/src/kernel/ao_log_micro.h index ec5cf3ed..f0243028 100644 --- a/src/kernel/ao_log_micro.h +++ b/src/kernel/ao_log_micro.h @@ -23,7 +23,9 @@  #define PA_MIN_OFFSET		4  #define N_SAMPLES_OFFSET	8  #define STARTING_LOG_OFFSET	10 +#ifndef MAX_LOG_OFFSET  #define MAX_LOG_OFFSET		512 +#endif  void  ao_log_micro_save(void); diff --git a/src/kernel/ao_microkalman.c b/src/kernel/ao_microkalman.c index ff543cc4..3cfb87cc 100644 --- a/src/kernel/ao_microkalman.c +++ b/src/kernel/ao_microkalman.c @@ -32,10 +32,32 @@  #include <ao_kalman.h> +#ifndef AO_MK_STEP_96MS +#define AO_MK_STEP_96MS	1 + +#endif + +#if AO_MK_STEP_100MS +#define AO_MK_TIME_STEP	0.1 + +#define AO_K0_10	AO_MK2_BARO_K0_10 +#define AO_K1_10	AO_MK2_BARO_K1_10 +#define AO_K2_10	AO_MK2_BARO_K2_10 +#endif + +#if AO_MK_STEP_96MS +#define AO_MK_TIME_STEP	0.096 + +#define AO_K0_10	AO_MK_BARO_K0_10 +#define AO_K1_10	AO_MK_BARO_K1_10 +#define AO_K2_10	AO_MK_BARO_K2_10 +#endif +  /* Basic time step (96ms) */ -#define AO_MK_STEP	to_fix_v(0.096) +#define AO_MK_STEP	to_fix_v(AO_MK_TIME_STEP) +  /* step ** 2 / 2 */ -#define AO_MK_STEP_2_2	to_fix_v(0.004608) +#define AO_MK_STEP_2_2	to_fix_v(AO_MK_TIME_STEP * AO_MK_TIME_STEP / 2.0)  uint32_t	ao_k_pa;		/* 24.8 fixed point */  int32_t		ao_k_pa_speed;		/* 16.16 fixed point */ @@ -66,9 +88,9 @@ ao_microkalman_correct(void)  	e = pa - from_fix8(ao_k_pa); -	ao_k_pa       += fix16_to_fix8((int32_t) e * AO_MK_BARO_K0_10); -	ao_k_pa_speed += (int32_t) e * AO_MK_BARO_K1_10; -	ao_k_pa_accel += (int32_t) e * AO_MK_BARO_K2_10; +	ao_k_pa       += fix16_to_fix8((int32_t) e * AO_K0_10); +	ao_k_pa_speed += (int32_t) e * AO_K1_10; +	ao_k_pa_accel += (int32_t) e * AO_K2_10;  	ao_pa = from_fix8(ao_k_pa);  	ao_pa_speed = from_fix(ao_k_pa_speed);  	ao_pa_accel = from_fix(ao_k_pa_accel); diff --git a/src/kernel/ao_report_micro.c b/src/kernel/ao_report_micro.c index af68457d..9c7afdc5 100644 --- a/src/kernel/ao_report_micro.c +++ b/src/kernel/ao_report_micro.c @@ -17,6 +17,7 @@   */  #include <ao.h> +#include <ao_report_micro.h>  #define mid(time)	ao_led_for(AO_LED_REPORT, time)  #define pause(time)	ao_delay(time) diff --git a/src/kernel/ao_report_micro.h b/src/kernel/ao_report_micro.h new file mode 100644 index 00000000..bd6c0622 --- /dev/null +++ b/src/kernel/ao_report_micro.h @@ -0,0 +1,21 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +#ifndef _AO_REPORT_MICRO_H_ +#define _AO_REPORT_MICRO_H_ + +void +ao_report_altitude(void); + +#endif /* _AO_REPORT_MICRO_H_ */ diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index fa817824..2ae1e41b 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -160,8 +160,8 @@ ao_send_mega_sensor(void)  #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; +	telemetry.mega_sensor.mag_y = packet->hmc5883.y;  #endif  	ao_telemetry_send(); @@ -296,6 +296,10 @@ static __pdata int8_t ao_telemetry_config_max;  static __pdata int8_t ao_telemetry_config_cur;  static __pdata uint16_t ao_telemetry_flight_number; +#ifndef ao_telemetry_battery_convert +#define ao_telemetry_battery_convert(a) (a) +#endif +  static void  ao_send_configuration(void)  { @@ -308,7 +312,7 @@ ao_send_configuration(void)  		telemetry.configuration.config_minor = AO_CONFIG_MINOR;  #if AO_idProduct_NUMBER == 0x25 && HAS_ADC  		/* TeleGPS gets battery voltage instead of apogee delay */ -		telemetry.configuration.apogee_delay = ao_data_ring[ao_data_ring_prev(ao_data_head)].adc.v_batt; +		telemetry.configuration.apogee_delay = ao_telemetry_battery_convert(ao_data_ring[ao_data_ring_prev(ao_data_head)].adc.v_batt);  #else  		telemetry.configuration.apogee_delay = ao_config.apogee_delay;  		telemetry.configuration.main_deploy = ao_config.main_deploy; diff --git a/src/kernel/ao_telemetry.h b/src/kernel/ao_telemetry.h index 45aaeb07..23e3ed7d 100644 --- a/src/kernel/ao_telemetry.h +++ b/src/kernel/ao_telemetry.h @@ -198,8 +198,8 @@ struct ao_telemetry_mega_sensor {  	int16_t		gyro_z;		/* 24 */  	int16_t		mag_x;		/* 26 */ -	int16_t		mag_y;		/* 28 */ -	int16_t		mag_z;		/* 30 */ +	int16_t		mag_z;		/* 28 */ +	int16_t		mag_y;		/* 30 */  	/* 32 */  }; diff --git a/src/kernel/ao_tracker.c b/src/kernel/ao_tracker.c index 4abd309a..46278530 100644 --- a/src/kernel/ao_tracker.c +++ b/src/kernel/ao_tracker.c @@ -164,6 +164,25 @@ ao_tracker(void)  	}  } +#ifdef AO_LED_GPS_LOCK + +static struct ao_task ao_gps_lock_task; + +static void +ao_gps_lock(void) +{ +	for (;;) { +		if ((gps_data.flags & (AO_GPS_VALID|AO_GPS_COURSE_VALID)) == +		    (AO_GPS_VALID|AO_GPS_COURSE_VALID)) +		{ +			ao_led_for(AO_LED_GPS_LOCK, AO_MS_TO_TICKS(20)); +		} +		ao_delay(AO_SEC_TO_TICKS(3)); +	} +} +#endif + +  static uint8_t erasing_current;  void @@ -222,4 +241,7 @@ ao_tracker_init(void)  #endif  	ao_cmd_register(&ao_tracker_cmds[0]);  	ao_add_task(&ao_tracker_task, ao_tracker, "tracker"); +#ifdef AO_LED_GPS_LOCK +	ao_add_task(&ao_gps_lock_task, ao_gps_lock, "gps lock"); +#endif  } diff --git a/src/kernel/ao_usb.h b/src/kernel/ao_usb.h index cdea5178..936d939b 100644 --- a/src/kernel/ao_usb.h +++ b/src/kernel/ao_usb.h @@ -155,6 +155,8 @@ struct ao_usb_line_coding {  	uint8_t		data_bits;  } ; +extern __xdata struct ao_usb_line_coding ao_usb_line_coding; +  extern __pdata uint8_t ao_usb_running;  #endif /* _AO_USB_H_ */ diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 5c13eb4b..c50e7528 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -477,7 +477,7 @@ ao_usb_ep0_in_start(uint16_t max)  	ao_usb_ep0_flush();  } -static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; +struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};  /* Walk through the list of descriptors and find a match   */ diff --git a/src/micropeak-v2.0/.gitignore b/src/micropeak-v2.0/.gitignore new file mode 100644 index 00000000..c2062c34 --- /dev/null +++ b/src/micropeak-v2.0/.gitignore @@ -0,0 +1,3 @@ +ao_product.h +microsplash-v* +microsplash-load diff --git a/src/micropeak-v2.0/Makefile b/src/micropeak-v2.0/Makefile new file mode 100644 index 00000000..32154fa6 --- /dev/null +++ b/src/micropeak-v2.0/Makefile @@ -0,0 +1,100 @@ +# +# Tiny AltOS build +# +# + +include ../stmf0/Makefile.defs + +PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries +PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX) + +MICRO_SRC=\ +	ao_report_micro.c \ +	ao_log_micro.c \ +	ao_microflight.c \ +	ao_microkalman.c + +ALTOS_SRC = \ +	ao_micropeak.c \ +	ao_spi_stm.c \ +	ao_dma_stm.c \ +	ao_led.c \ +	ao_timer.c \ +	ao_ms5607.c \ +	ao_exti_stm.c \ +	ao_convert_pa.c \ +	ao_romconfig.c \ +	ao_product.c \ +	ao_panic.c \ +	ao_stdio.c \ +	ao_serial_stm.c \ +	ao_usb_stm.c \ +	ao_mutex.c \ +	ao_interrupt.c \ +	ao_cmd.c \ +	ao_task.c \ +	ao_data.c \ +	ao_boot_chain.c \ +	ao_microflight.c \ +	ao_report_micro.c \ +	ao_storage_stm.c \ +	ao_storage.c \ +	ao_log_micro.c \ +	ao_microkalman.c + +INC=\ +	ao.h \ +	ao_pins.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_exti.h \ +	ao_ms5607.h \ +	ao_log_micro.h \ +	ao_micropeak.h \ +	altitude-pa.h \ +	stm32f0.h + +IDPRODUCT=0x14 +PRODUCT=MicroPeak-v2.0 +PRODUCT_DEF=-DMICROPEAK + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os + +PROGNAME=micropeak-v2.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tmicropeak.ld -n + +$(PROG): Makefile $(OBJ) micropeak.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.o: ao_product.c ao_product.h + +distclean:	clean + +clean: +	rm -f *.o *.elf *.ihx +	rm -f ao_product.h + +publish: $(PUBLISH_HEX) + +$(PUBLISH_HEX): $(HEX) +	cp -a $(HEX) $@ + +../altitude-pa.h: make-altitude-pa +	nickle $< > $@ + +install: + +uninstall: + +$(OBJ): ao_product.h $(INC) diff --git a/src/micropeak-v2.0/ao_micropeak.c b/src/micropeak-v2.0/ao_micropeak.c new file mode 100644 index 00000000..1cfa1209 --- /dev/null +++ b/src/micropeak-v2.0/ao_micropeak.c @@ -0,0 +1,278 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_exti.h> +#include <ao_micropeak.h> +#include <ao_report_micro.h> +#include <ao_log_micro.h> +#include <ao_storage.h> + +static struct ao_ms5607_value	value; + +alt_t		ground_alt, max_alt; +alt_t		ao_max_height; + +void +ao_pa_get(void) +{ +	ao_ms5607_sample(&ao_ms5607_current); +	ao_ms5607_convert(&ao_ms5607_current, &value); +	pa = value.pres; +} + +static void +ao_compute_height(void) +{ +	ground_alt = ao_pa_to_altitude(pa_ground); +	max_alt = ao_pa_to_altitude(pa_min); +	ao_max_height = max_alt - ground_alt; +} + +static void +ao_pips(void) +{ +	uint8_t	i; +	for (i = 0; i < 10; i++) { +		ao_led_toggle(AO_LED_REPORT); +		ao_delay(AO_MS_TO_TICKS(80)); +	} +	ao_delay(AO_MS_TO_TICKS(200)); +} + +void +ao_delay_until(uint16_t target) { +	int16_t	delay = target - ao_time(); +	if (delay > 0) { +		ao_sleep_for(ao_delay_until, delay); +	} +} + +static struct ao_task mp_task; + +static void +ao_battery_disable(void) +{ +	/* Disable */ +	if (stm_adc.cr & (1 << STM_ADC_CR_ADEN)) { +		stm_adc.cr |= (1 << STM_ADC_CR_ADDIS); +		while (stm_adc.cr & (1 << STM_ADC_CR_ADDIS)) +			; +	} + +	/* Turn off everything */ +	stm_adc.cr &= ~((1 << STM_ADC_CR_ADCAL) | +			(1 << STM_ADC_CR_ADSTP) | +			(1 << STM_ADC_CR_ADSTART) | +			(1 << STM_ADC_CR_ADEN)); +} + +static void +ao_battery_init(void) +{ +	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADCEN); + +	ao_battery_disable(); + +	/* Configure */ +	stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) |				  /* analog watchdog channel 0 */ +			 (0 << STM_ADC_CFGR1_AWDEN) |				  /* Disable analog watchdog */ +			 (0 << STM_ADC_CFGR1_AWDSGL) |				  /* analog watchdog on all channels */ +			 (0 << STM_ADC_CFGR1_DISCEN) |				  /* Not discontinuous mode. All channels converted with one trigger */ +			 (0 << STM_ADC_CFGR1_AUTOOFF) |				  /* Leave ADC running */ +			 (1 << STM_ADC_CFGR1_WAIT) |				  /* Wait for data to be read before next conversion */ +			 (0 << STM_ADC_CFGR1_CONT) |				  /* only one set of conversions per trigger */ +			 (1 << STM_ADC_CFGR1_OVRMOD) |				  /* overwrite on overrun */ +			 (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) |	  /* SW trigger */ +			 (0 << STM_ADC_CFGR1_ALIGN) |				  /* Align to LSB */ +			 (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) |		  /* 12 bit resolution */ +			 (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) |	  /* scan 0 .. n */ +			 (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) | /* one set of conversions then stop */ +			 (1 << STM_ADC_CFGR1_DMAEN));				  /* enable DMA */ + +	/* Set the clock */ +	stm_adc.cfgr2 = STM_ADC_CFGR2_CKMODE_PCLK_2 << STM_ADC_CFGR2_CKMODE; + +	/* Shortest sample time */ +	stm_adc.smpr = STM_ADC_SMPR_SMP_71_5 << STM_ADC_SMPR_SMP; + +	/* Select Vref */ +	stm_adc.chselr = 1 << 17; + +	stm_adc.ccr = ((0 << STM_ADC_CCR_VBATEN) | +		       (0 << STM_ADC_CCR_TSEN) | +		       (1 << STM_ADC_CCR_VREFEN)); + +	/* Calibrate */ +	stm_adc.cr |= (1 << STM_ADC_CR_ADCAL); +	while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0) +		; + +	/* Enable */ +	stm_adc.cr |= (1 << STM_ADC_CR_ADEN); +	while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0) +		; + +	/* Clear any stale status bits */ +	stm_adc.isr = 0; + +	/* Turn on syscfg */ +	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN); +} + +static void +ao_battery_fini(void) +{ +	/* Disable */ +	ao_battery_disable(); + +	/* Power down */ +	stm_rcc.apb2enr &= ~(1 << STM_RCC_APB2ENR_ADCEN); +} + +static uint16_t +ao_battery_voltage(void) +{ +	uint16_t	vrefint; + +	ao_battery_init(); + +	stm_adc.cr |= (1 << STM_ADC_CR_ADSTART); + +	while ((stm_adc.isr & (1 << STM_ADC_ISR_EOC)) == 0) +		ao_arch_nop(); + +	vrefint = stm_adc.dr; + +	ao_battery_fini(); + +	return 330 * stm_cal.vrefint_cal / vrefint; +} + + +uint8_t	ao_on_battery; + +static void +ao_micropeak(void) +{ +	ao_ms5607_setup(); +	ao_storage_setup(); + +	/* Give the person a second to get their finger out of the way */ +	ao_delay(AO_MS_TO_TICKS(1000)); + +	ao_pips(); + +	ao_log_micro_restore(); +	ao_compute_height(); +	ao_report_altitude(); +	ao_log_micro_dump(); + +#if BOOST_DELAY +	ao_delay(BOOST_DELAY); +#endif + +	ao_microflight(); + +	ao_log_micro_save(); +	ao_compute_height(); +	ao_report_altitude(); + +	ao_sleep(&ao_on_battery); +} + +static void +ao_show_bat(void) +{ +	printf("battery: %u\n", ao_battery_voltage()); +} + +static struct ao_cmds mp_cmd[] = { +	{ ao_show_bat, "b\0Show battery voltage" }, +	{ 0 } +}; + +static void +ao_hsi_init(void) +{ +	uint32_t	cfgr; + +	/* Disable all interrupts */ +	stm_rcc.cir = 0; + +	/* Enable prefetch */ +	stm_flash.acr |= (1 << STM_FLASH_ACR_PRFTBE); + +	/* Enable power interface clock */ +	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + +	/* HCLK to 48MHz -> AHB prescaler = /1 */ +	cfgr = stm_rcc.cfgr; +	cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << 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)) != +	       (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE)) +		ao_arch_nop(); + +	/* APB Prescaler = AO_APB_PRESCALER */ +	cfgr = stm_rcc.cfgr; +	cfgr &= ~(STM_RCC_CFGR_PPRE_MASK << STM_RCC_CFGR_PPRE); +	cfgr |= (AO_RCC_CFGR_PPRE_DIV << STM_RCC_CFGR_PPRE); +	stm_rcc.cfgr = cfgr; + +	/* Clear reset flags */ +	stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF); +} + +void +main(void) +{ +	if (ao_battery_voltage() < 320) +		ao_on_battery = 1; + +	/* Leave the system running on the HSI if we're on battery */ +	if (!ao_on_battery) +		ao_clock_init(); +	else +		ao_hsi_init(); + +	ao_led_init(LEDS_AVAILABLE); +	ao_task_init(); +	ao_timer_init(); +	ao_serial_init(); +	stm_moder_set(&stm_gpioa, 2, STM_MODER_OUTPUT); + +	ao_dma_init(); +	ao_spi_init(); +	ao_exti_init(); + +	/* Leave USB disabled on battery */ +	if (!ao_on_battery) { +		ao_usb_init(); +		ao_cmd_init(); +	} + +	ao_ms5607_init(); + +	ao_storage_init(); + +	ao_add_task(&mp_task, ao_micropeak, "micropeak"); +	ao_cmd_register(mp_cmd); +	ao_start_scheduler(); +} diff --git a/src/micropeak-v2.0/ao_pins.h b/src/micropeak-v2.0/ao_pins.h new file mode 100644 index 00000000..fa2ed804 --- /dev/null +++ b/src/micropeak-v2.0/ao_pins.h @@ -0,0 +1,145 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +extern uint8_t ao_on_battery; + +#define AO_SYSCLK	(ao_on_battery ? STM_HSI_FREQ : 48000000) + +#define LED_PORT_ENABLE	STM_RCC_AHBENR_IOPAEN +#define LED_PORT	(&stm_gpioa) +#define LED_PIN_ORANGE	2 +#define AO_LED_ORANGE	(1 << LED_PIN_ORANGE) +#define AO_LED_REPORT	AO_LED_ORANGE +#define AO_LED_PANIC	AO_LED_ORANGE + +#define LEDS_AVAILABLE	(AO_LED_ORANGE) + +#define AO_POWER_MANAGEMENT	0 + +/* 48MHz clock based on USB */ +#define AO_HSI48	1 +/* Need HSI running to flash */ +#define AO_NEED_HSI	1 + +/* HCLK = 12MHz usb / 2MHz battery */ +#define AO_AHB_PRESCALER	(ao_on_battery ? 16 : 1) +#define AO_RCC_CFGR_HPRE_DIV	(ao_on_battery ? STM_RCC_CFGR_HPRE_DIV_16 : STM_RCC_CFGR_HPRE_DIV_1) + +/* APB = 12MHz usb / 2MHz battery */ +#define AO_APB_PRESCALER	1 +#define AO_RCC_CFGR_PPRE_DIV	STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB			1 +#define AO_PA11_PA12_RMP	1 + +#define PACKET_HAS_SLAVE	0 +#define HAS_SERIAL_1		0 +#define HAS_SERIAL_2		1 +#define USE_SERIAL_2_STDIN	0 +#define USE_SERIAL_2_FLOW	0 +#define USE_SERIAL_2_SW_FLOW	0 +#define SERIAL_2_PA2_PA3	1 +#define SERIAL_2_PA14_PA15	0 +#define USE_SERIAL2_FLOW	0 +#define USE_SERIAL2_SW_FLOW	0 + +#define IS_FLASH_LOADER		0 + +#define HAS_MS5607		1 +#define HAS_MS5611		0 +#define HAS_MS5607_TASK		0 +#define HAS_EEPROM		0 +#define HAS_BEEP		0 + +/* Logging */ +#define LOG_INTERVAL		1 +#define SAMPLE_SLEEP		AO_MS_TO_TICKS(100) +#define BOOST_DELAY		AO_SEC_TO_TICKS(60) +#define AO_LOG_ID		AO_LOG_ID_MICRO_PEAK2 + +/* Kalman filter */ + +#define AO_MK_STEP_100MS	1 +#define AO_MK_STEP_96MS		0 + +/* SPI */ +#define HAS_SPI_1		1 +#define SPI_1_PA5_PA6_PA7	1 +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_OSPEEDR		STM_OSPEEDR_MEDIUM + +#define HAS_SPI_2		0 + +/* MS5607 */ +#define HAS_MS5607		1 +#define HAS_MS5611		0 +#define AO_MS5607_PRIVATE_PINS	0 +#define AO_MS5607_CS_PORT	(&stm_gpioa) +#define AO_MS5607_CS_PIN	4 +#define AO_MS5607_CS_MASK	(1 << AO_MS5607_CS_PIN) +#define AO_MS5607_MISO_PORT	(&stm_gpioa) +#define AO_MS5607_MISO_PIN	6 +#define AO_MS5607_MISO_MASK	(1 << AO_MS5607_MISO_PIN) +#define AO_MS5607_SPI_INDEX	AO_SPI_1_PA5_PA6_PA7 + +typedef int32_t alt_t; + +#define AO_ALT_VALUE(x)		((x) * (alt_t) 10) + +#define AO_DATA_RING		32 + +#define HAS_ADC			0 + +static inline void +ao_power_off(void) __attribute((noreturn)); + +static inline void +ao_power_off(void) { +	for (;;) { +	} +} + +extern alt_t ao_max_height; + +void ao_delay_until(uint16_t target); + +#define ao_async_stop() do {					\ +		ao_serial2_drain();				\ +		stm_moder_set(&stm_gpioa, 2, STM_MODER_OUTPUT); \ +	} while (0) + +#define ao_async_start() do {						\ +		stm_moder_set(&stm_gpioa, 2, STM_MODER_ALTERNATE);	\ +		ao_delay(AO_MS_TO_TICKS(100));				\ +	} while (0) + +#define ao_async_byte(b) ao_serial2_putchar((char) (b)) + +#define ao_eeprom_read(pos, ptr, size) ao_storage_read(pos, ptr, size) +#define ao_eeprom_write(pos, ptr, size) ao_storage_write(pos, ptr, size) +#define MAX_LOG_OFFSET	ao_storage_total + +extern uint32_t __flash__[]; +extern uint32_t __flash_end__[]; + +#define AO_BOOT_APPLICATION_BOUND	((uint32_t *) __flash__) +#define USE_STORAGE_CONFIG	0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/micropeak-v2.0/flash-loader/.gitignore b/src/micropeak-v2.0/flash-loader/.gitignore new file mode 100644 index 00000000..43f0aa8d --- /dev/null +++ b/src/micropeak-v2.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +*.bin +*.elf diff --git a/src/micropeak-v2.0/flash-loader/Makefile b/src/micropeak-v2.0/flash-loader/Makefile new file mode 100644 index 00000000..4e30c1c6 --- /dev/null +++ b/src/micropeak-v2.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=micropeak-v2.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/micropeak-v2.0/flash-loader/ao_pins.h b/src/micropeak-v2.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..196a8b1d --- /dev/null +++ b/src/micropeak-v2.0/flash-loader/ao_pins.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include <ao_flash_stm_pins.h> + +/* LED anode (PA2) to 3.3 for boot mode */ + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpioa +#define AO_BOOT_APPLICATION_PIN		2 +#define AO_BOOT_APPLICATION_VALUE	0 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_DOWN + +/* USB */ +#define HAS_USB			1 +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/micropeak-v2.0/micropeak.ld b/src/micropeak-v2.0/micropeak.ld new file mode 100644 index 00000000..77717e16 --- /dev/null +++ b/src/micropeak-v2.0/micropeak.ld @@ -0,0 +1,123 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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. + */ + +MEMORY { +	rom (rx) :   ORIGIN = 0x08001000, LENGTH = 20K +	flash(rx) :  ORIGIN = 0x08006000, LENGTH = 8K +	ram (!w) :   ORIGIN = 0x20000000, LENGTH = 6k - 128 +	stack (!w) : ORIGIN = 0x20000000 + 6k - 128, LENGTH = 128 +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) + +SECTIONS { +	/* +	 * Rom contents +	 */ + +	.interrupt ORIGIN(ram) : AT (ORIGIN(rom)) { +		__interrupt_start__ = .; +		__interrupt_rom__ = ORIGIN(rom); +		*(.interrupt)	/* Interrupt vectors */ +		__interrupt_end__ = .; +	} > ram + +	.text ORIGIN(rom) + 0x100 : { +		__text_start__ = .; + +		/* Ick. What I want is to specify the +		 * addresses of some global constants so +		 * that I can find them across versions +		 * of the application. I can't figure out +		 * how to make gnu ld do that, so instead +		 * we just load the two files that include +		 * these defines in the right order here and +		 * expect things to 'just work'. Don't change +		 * the contents of those files, ok? +		 */ +		ao_romconfig.o(.romconfig*) +		ao_product.o(.romconfig*) + +		*(.text*)	/* Executable code */ +	} > rom + +	.ARM.exidx : { +		*(.ARM.exidx* .gnu.linkonce.armexidx.*) +	} > rom + +	.rodata : { +		*(.rodata*)	/* Constants */ +	} > rom + +	__text_end__ = .; + +	/* Boot data which must live at the start of ram so that +	 * the application and bootloader share the same addresses. +	 * This must be all uninitialized data +	 */ +	.boot (NOLOAD) : { +		__boot_start__ = .; +		*(.boot) +		. = ALIGN(4); +		__boot_end__ = .; +	} >ram + +	/* Functions placed in RAM (required for flashing) +	 * +	 * Align to 8 bytes as that's what the ARM likes text +	 * segment alignments to be, and if we don't, then +	 * we end up with a mismatch between the location in +	 * ROM and the desired location in RAM. I don't +	 * entirely understand this, but at least this appears +	 * to work... +	 */ + +	.textram BLOCK(8): { +		__data_start__ = .; +		*(.ramtext) +	} >ram AT>rom + +	/* Data -- relocated to RAM, but written to ROM +	 */ +	.data : { +		*(.data)	/* initialized data */ +		. = ALIGN(4); +		__data_end__ = .; +	} >ram AT>rom + +	.bss : { +		__bss_start__ = .; +		*(.bss) +		*(COMMON) +		. = ALIGN(4); +		__bss_end__ = .; +	} >ram + +	PROVIDE(end = .); + +	PROVIDE(__flash__ = ORIGIN(flash)); +	PROVIDE(__flash_end__ = ORIGIN(flash) + LENGTH(flash)); + +	PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); +} + +ENTRY(start); + + diff --git a/src/nucleao-32/Makefile b/src/nucleao-32/Makefile index 69049982..2b9fe14f 100644 --- a/src/nucleao-32/Makefile +++ b/src/nucleao-32/Makefile @@ -60,7 +60,7 @@ IDPRODUCT=0x000a  CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g -LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tload.ld +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tload.ld -n  PROGNAME=nucleo-32  PROG=$(PROGNAME)-$(VERSION).elf diff --git a/src/nucleao-32/ao_lisp_os.h b/src/nucleao-32/ao_lisp_os.h new file mode 100644 index 00000000..1993ac44 --- /dev/null +++ b/src/nucleao-32/ao_lisp_os.h @@ -0,0 +1,62 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LISP_OS_H_ +#define _AO_LISP_OS_H_ + +#include "ao.h" + +static inline int +ao_lisp_getc() { +	static uint8_t	at_eol; +	int c; + +	if (at_eol) { +		ao_cmd_readline(); +		at_eol = 0; +	} +	c = ao_cmd_lex(); +	if (c == '\n') +		at_eol = 1; +	return c; +} + +static inline void +ao_lisp_os_flush(void) +{ +	flush(); +} + +static inline void +ao_lisp_abort(void) +{ +	ao_panic(1); +} + +static inline void +ao_lisp_os_led(int led) +{ +	ao_led_set(led); +} + +static inline void +ao_lisp_os_delay(int delay) +{ +	ao_delay(AO_MS_TO_TICKS(delay)); +} + +#endif diff --git a/src/nucleao-32/ao_lisp_os_save.c b/src/nucleao-32/ao_lisp_os_save.c new file mode 100644 index 00000000..cd740ccd --- /dev/null +++ b/src/nucleao-32/ao_lisp_os_save.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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. + */ + +#include <ao.h> +#include <ao_lisp.h> +#include <ao_flash.h> + +extern uint8_t	__flash__[] __attribute__((aligned(4))); + +/* saved variables to rebuild the heap + +   ao_lisp_atoms +   ao_lisp_frame_global + */ + +int +ao_lisp_os_save(void) +{ +	int i; + +	for (i = 0; i < AO_LISP_POOL_TOTAL; i += 256) { +		uint32_t	*dst = (uint32_t *) (void *) &__flash__[i]; +		uint32_t	*src = (uint32_t *) (void *) &ao_lisp_pool[i]; + +		ao_flash_page(dst, src); +	} +	return 1; +} + +int +ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset) +{ +	memcpy(save, &__flash__[offset], sizeof (struct ao_lisp_os_save)); +	return 1; +} + +int +ao_lisp_os_restore(void) +{ +	memcpy(ao_lisp_pool, __flash__, AO_LISP_POOL_TOTAL); +	return 1; +} diff --git a/src/nucleao-32/load.ld b/src/nucleao-32/load.ld new file mode 100644 index 00000000..02a23a95 --- /dev/null +++ b/src/nucleao-32/load.ld @@ -0,0 +1,108 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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. + */ + +MEMORY { +	rom (rx) :   ORIGIN = 0x08001000, LENGTH = 27K +	flash (rx) : ORIGIN = 0x08007c00, LENGTH = 1K +	ram (!w) :   ORIGIN = 0x20000000, LENGTH = 6k - 128 +	stack (!w) : ORIGIN = 0x20000000 + 6k - 128, LENGTH = 128 +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) + +SECTIONS { +	/* +	 * Rom contents +	 */ + +	.interrupt ORIGIN(ram) : AT (ORIGIN(rom)) { +		__interrupt_start__ = .; +		__interrupt_rom__ = ORIGIN(rom); +		*(.interrupt)	/* Interrupt vectors */ +		__interrupt_end__ = .; +	} > ram + +	.text ORIGIN(rom) + 0x100 : { +		__text_start__ = .; + +		/* Ick. What I want is to specify the +		 * addresses of some global constants so +		 * that I can find them across versions +		 * of the application. I can't figure out +		 * how to make gnu ld do that, so instead +		 * we just load the two files that include +		 * these defines in the right order here and +		 * expect things to 'just work'. Don't change +		 * the contents of those files, ok? +		 */ +		ao_romconfig.o(.romconfig*) +		ao_product.o(.romconfig*) + +		*(.text*)	/* Executable code */ +	} > rom + +	.ARM.exidx : { +		*(.ARM.exidx* .gnu.linkonce.armexidx.*) +	} > rom + +	.rodata : { +		*(.rodata*)	/* Constants */ +	} > rom + +	__text_end__ = .; + +	/* Boot data which must live at the start of ram so that +	 * the application and bootloader share the same addresses. +	 * This must be all uninitialized data +	 */ +	.boot (NOLOAD) : { +		__boot_start__ = .; +		*(.boot) +		. = ALIGN(4); +		__boot_end__ = .; +	} >ram + +	/* Data -- relocated to RAM, but written to ROM +	 */ +	.data : { +		__data_start__ = .; +		*(.data)	/* initialized data */ +		. = ALIGN(4); +		__data_end__ = .; +	} >ram AT>rom + +	.bss : { +		__bss_start__ = .; +		*(.bss) +		*(COMMON) +		. = ALIGN(4); +		__bss_end__ = .; +	} >ram + +	PROVIDE(end = .); + +	PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); + +	__flash__ = ORIGIN(flash); +} + +ENTRY(start); + + diff --git a/src/product/ao_micropeak.c b/src/product/ao_micropeak.c index f9960eb8..8aac79cd 100644 --- a/src/product/ao_micropeak.c +++ b/src/product/ao_micropeak.c @@ -22,7 +22,6 @@  #include <ao_log_micro.h>  #include <ao_async.h> -static struct ao_ms5607_sample	sample;  static struct ao_ms5607_value	value;  alt_t		ground_alt, max_alt; @@ -31,8 +30,8 @@ alt_t		ao_max_height;  void  ao_pa_get(void)  { -	ao_ms5607_sample(&sample); -	ao_ms5607_convert(&sample, &value); +	ao_ms5607_sample(&ao_ms5607_current); +	ao_ms5607_convert(&ao_ms5607_current, &value);  	pa = value.pres;  } diff --git a/src/product/ao_micropeak.h b/src/product/ao_micropeak.h index 6dc7a465..240eed59 100644 --- a/src/product/ao_micropeak.h +++ b/src/product/ao_micropeak.h @@ -19,7 +19,9 @@  #ifndef _AO_MICROPEAK_H_  #define _AO_MICROPEAK_H_ +#ifndef SAMPLE_SLEEP  #define SAMPLE_SLEEP		AO_MS_TO_TICKS(96) +#endif  /* 64 sample, or about six seconds worth */  #define GROUND_AVG_SHIFT	6 @@ -36,6 +38,7 @@  #define AO_LOG_ID_MICROPEAK	0  #define AO_LOG_ID_MICROKITE	1 +#define AO_LOG_ID_MICROPEAK2	2  #ifndef AO_LOG_ID  #define AO_LOG_ID		AO_LOG_ID_MICROPEAK diff --git a/src/product/ao_telemini.c b/src/product/ao_telemini.c index b192763d..14414a48 100644 --- a/src/product/ao_telemini.c +++ b/src/product/ao_telemini.c @@ -19,8 +19,6 @@  #include "ao.h"  #include "ao_pins.h" -__xdata uint8_t ao_force_freq; -  void  main(void)  { diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index c625471e..ef562313 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -195,7 +195,7 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)  }  static void -ao_usart_init(struct ao_stm_usart *usart) +ao_usart_init(struct ao_stm_usart *usart, int hw_flow)  {  	usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) |  			  (1 << STM_USART_CR1_UE) | @@ -236,6 +236,10 @@ ao_usart_init(struct ao_stm_usart *usart)  			  (0 << STM_USART_CR3_IREN) |  			  (0 << STM_USART_CR3_EIE)); +	if (hw_flow) +		usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | +				    (1 << STM_USART_CR3_RTSE)); +  	/* Pick a 9600 baud rate */  	ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);  } @@ -244,8 +248,6 @@ ao_usart_init(struct ao_stm_usart *usart)  static void  ao_usart_set_flow(struct ao_stm_usart *usart)  { -	usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | -			    (1 << STM_USART_CR3_RTSE));  }  #endif @@ -441,7 +443,7 @@ ao_serial_init(void)  	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN);  	ao_stm_usart1.reg = &stm_usart1; -	ao_usart_init(&ao_stm_usart1); +	ao_usart_init(&ao_stm_usart1, 0);  	stm_nvic_set_enable(STM_ISR_USART1_POS);  	stm_nvic_set_priority(STM_ISR_USART1_POS, AO_STM_NVIC_MED_PRIORITY); @@ -494,10 +496,7 @@ ao_serial_init(void)  	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN);  	ao_stm_usart2.reg = &stm_usart2; -	ao_usart_init(&ao_stm_usart2); -#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW -	ao_usart_set_flow(&ao_stm_usart2); -#endif +	ao_usart_init(&ao_stm_usart2, USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW);  	stm_nvic_set_enable(STM_ISR_USART2_POS);  	stm_nvic_set_priority(STM_ISR_USART2_POS, AO_STM_NVIC_MED_PRIORITY); @@ -541,7 +540,7 @@ ao_serial_init(void)  	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN);  	ao_stm_usart3.reg = &stm_usart3; -	ao_usart_init(&ao_stm_usart3); +	ao_usart_init(&ao_stm_usart3, 0);  	stm_nvic_set_enable(STM_ISR_USART3_POS);  	stm_nvic_set_priority(STM_ISR_USART3_POS, AO_STM_NVIC_MED_PRIORITY); diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 33e0617c..595bddac 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -598,7 +598,7 @@ ao_usb_ep0_in_start(uint16_t max)  	ao_usb_ep0_flush();  } -static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; +struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};  /* Walk through the list of descriptors and find a match   */ diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h index c5f451f5..5c5085d9 100644 --- a/src/stmf0/ao_arch.h +++ b/src/stmf0/ao_arch.h @@ -94,12 +94,17 @@ extern const uint32_t ao_radio_cal;   * For the stm32f042, we want to use the USB-based HSI48 clock   */ -#if AO_HSI48 +#ifndef AO_SYSCLK +#if AO_HSI +#define AO_SYSCLK	STM_HSI_FREQ +#endif +#if AO_HSI48  #define AO_SYSCLK	48000000 -#define AO_HCLK		(AO_SYSCLK / AO_AHB_PRESCALER) -  #endif +#endif + +#define AO_HCLK		(AO_SYSCLK / AO_AHB_PRESCALER)  #if AO_HSE || AO_HSI @@ -150,7 +155,9 @@ ao_adc_init();  #if HAS_BOOT_LOADER  #define AO_BOOT_APPLICATION_BASE	((uint32_t *) 0x08001000) +#ifndef AO_BOOT_APPLICATION_BOUND  #define AO_BOOT_APPLICATION_BOUND	((uint32_t *) (0x08000000 + stm_flash_size())) +#endif  #define AO_BOOT_LOADER_BASE		((uint32_t *) 0x08000000)  #endif diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index c38ce41a..01d51f90 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -310,6 +310,27 @@ void  ao_i2c_init(void);  /* ao_serial_stm.c */ + +#if USE_SERIAL_1_FLOW && USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && USE_SERIAL_2_SW_FLOW +#define HAS_SERIAL_SW_FLOW	1 +#else +#define HAS_SERIAL_SW_FLOW	0 +#endif + +#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW +#define USE_SERIAL_2_HW_FLOW	1 +#endif + +#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW +#define USE_SERIAL_1_HW_FLOW	1 +#endif + +#if USE_SERIAL_1_HW_FLOW || USE_SERIAL_2_HW_FLOW +#define HAS_SERIAL_HW_FLOW	1 +#else +#define HAS_SERIAL_HW_FLOW	0 +#endif +  struct ao_stm_usart {  	struct ao_fifo		rx_fifo;  	struct ao_fifo		tx_fifo; diff --git a/src/stmf0/ao_beep_stm.c b/src/stmf0/ao_beep_stm.c index 610f4a31..15137230 100644 --- a/src/stmf0/ao_beep_stm.c +++ b/src/stmf0/ao_beep_stm.c @@ -25,6 +25,10 @@  #define BEEPER_TIMER	1  #endif +#ifndef BEEPER_AFR +#define BEEPER_AFR	STM_AFR_AF2 +#endif +  #if BEEPER_TIMER == 1  #define timer stm_tim1  #define STM_RCC_TIMER STM_RCC_APB2ENR_TIM1EN @@ -366,7 +370,7 @@ ao_beep(uint8_t beep)  		timer.egr = (1 << STM_TIM23_EGR_UG);  		/* Hook the timer up to the beeper pin */ -		stm_afr_set(BEEPER_PORT, BEEPER_PIN, STM_AFR_AF2); +		stm_afr_set(BEEPER_PORT, BEEPER_PIN, BEEPER_AFR);  #endif  	}  } diff --git a/src/stmf0/ao_exti.h b/src/stmf0/ao_exti.h index 7452af8e..36c3f7ca 100644 --- a/src/stmf0/ao_exti.h +++ b/src/stmf0/ao_exti.h @@ -21,6 +21,7 @@  #define AO_EXTI_MODE_RISING	1  #define AO_EXTI_MODE_FALLING	2 +#define AO_EXTI_MODE_PULL_NONE	0  #define AO_EXTI_MODE_PULL_UP	4  #define AO_EXTI_MODE_PULL_DOWN	8  #define AO_EXTI_PRIORITY_LOW	16 diff --git a/src/stmf0/ao_serial_stm.c b/src/stmf0/ao_serial_stm.c index 30b0dbd2..59cfde2e 100644 --- a/src/stmf0/ao_serial_stm.c +++ b/src/stmf0/ao_serial_stm.c @@ -163,24 +163,12 @@ ao_usart_drain(struct ao_stm_usart *usart)  	ao_arch_release_interrupts();  } -static const struct { -	uint32_t brr; -} ao_usart_speeds[] = { -	[AO_SERIAL_SPEED_4800] = { -		AO_PCLK / 4800 -	}, -	[AO_SERIAL_SPEED_9600] = { -		AO_PCLK / 9600 -	}, -	[AO_SERIAL_SPEED_19200] = { -		AO_PCLK / 19200 -	}, -	[AO_SERIAL_SPEED_57600] = { -		AO_PCLK / 57600 -	}, -	[AO_SERIAL_SPEED_115200] = { -		AO_PCLK / 115200 -	}, +static const uint32_t ao_usart_speeds[] = { +	[AO_SERIAL_SPEED_4800] = 4800, +	[AO_SERIAL_SPEED_9600] = 9600, +	[AO_SERIAL_SPEED_19200] = 19200, +	[AO_SERIAL_SPEED_57600] = 57600, +	[AO_SERIAL_SPEED_115200] = 115200,  };  static void @@ -188,11 +176,11 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)  {  	if (speed > AO_SERIAL_SPEED_115200)  		return; -	usart->reg->brr = ao_usart_speeds[speed].brr; +	usart->reg->brr = AO_PCLK / ao_usart_speeds[speed];  }  static void -ao_usart_init(struct ao_stm_usart *usart) +ao_usart_init(struct ao_stm_usart *usart, int hw_flow)  {  	usart->reg->cr1 = ((0 << STM_USART_CR1_M1) |  			   (0 << STM_USART_CR1_EOBIE) | @@ -235,44 +223,39 @@ ao_usart_init(struct ao_stm_usart *usart)  			   (0 << STM_USART_CR2_LBDL) |  			   (0 << STM_USART_CR2_ADDM7)); -	usart->reg->cr3 = ((0 << STM_USART_CR3_WUFIE) | -			   (0 << STM_USART_CR3_WUS) | -			   (0 << STM_USART_CR3_SCARCNT) | -			   (0 << STM_USART_CR3_DEP) | -			   (0 << STM_USART_CR3_DEM) | -			   (0 << STM_USART_CR3_DDRE) | -			   (0 << STM_USART_CR3_OVRDIS) | -			   (0 << STM_USART_CR3_ONEBIT) | -			   (0 << STM_USART_CR3_CTIIE) | -			   (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)); - +	uint32_t cr3 = ((0 << STM_USART_CR3_WUFIE) | +			(0 << STM_USART_CR3_WUS) | +			(0 << STM_USART_CR3_SCARCNT) | +			(0 << STM_USART_CR3_DEP) | +			(0 << STM_USART_CR3_DEM) | +			(0 << STM_USART_CR3_DDRE) | +			(0 << STM_USART_CR3_OVRDIS) | +			(0 << STM_USART_CR3_ONEBIT) | +			(0 << STM_USART_CR3_CTIIE) | +			(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)); + +	if (hw_flow) +		cr3 |= ((1 << STM_USART_CR3_CTSE) | +			(1 << STM_USART_CR3_RTSE)); + +	usart->reg->cr3 = cr3;  	/* Pick a 9600 baud rate */  	ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);  	/* Enable the usart */  	usart->reg->cr1 |= (1 << STM_USART_CR1_UE); -  } -#if HAS_SERIAL_HW_FLOW -static void -ao_usart_set_flow(struct ao_stm_usart *usart) -{ -	usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | -			    (1 << STM_USART_CR3_RTSE)); -} -#endif -  #if HAS_SERIAL_1  struct ao_stm_usart ao_stm_usart1; @@ -360,7 +343,7 @@ ao_serial2_set_speed(uint8_t speed)  	ao_usart_set_speed(&ao_stm_usart2, speed);  } -#if HAS_SERIAL_SW_FLOW +#if USE_SERIAL_2_FLOW && USE_SERIAL_2_SW_FLOW  void  ao_serial2_cts(void)  { @@ -403,13 +386,13 @@ ao_serial_init(void)  	 */  #if SERIAL_1_PA9_PA10 -	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); +	ao_enable_port(&stm_gpioa);  	stm_afr_set(&stm_gpioa, 9, STM_AFR_AF1);  	stm_afr_set(&stm_gpioa, 10, STM_AFR_AF1);  #else  #if SERIAL_1_PB6_PB7 -	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); +	ao_enable_port(&stm_gpiob);  	stm_afr_set(&stm_gpiob, 6, STM_AFR_AF0);  	stm_afr_set(&stm_gpiob, 7, STM_AFR_AF0); @@ -421,7 +404,7 @@ ao_serial_init(void)  	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN);  	ao_stm_usart1.reg = &stm_usart1; -	ao_usart_init(&ao_stm_usart1); +	ao_usart_init(&ao_stm_usart1, 0);  	stm_nvic_set_enable(STM_ISR_USART1_POS);  	stm_nvic_set_priority(STM_ISR_USART1_POS, 4); @@ -440,8 +423,7 @@ ao_serial_init(void)  	 */  # if SERIAL_2_PA2_PA3 -	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); - +	ao_enable_port(&stm_gpioa);  	stm_afr_set(&stm_gpioa, 2, STM_AFR_AF1);  	stm_afr_set(&stm_gpioa, 3, STM_AFR_AF1);  #  if USE_SERIAL_2_FLOW @@ -459,8 +441,7 @@ ao_serial_init(void)  #  endif  # else  #  if SERIAL_2_PA14_PA15 -	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); - +	ao_enable_port(&stm_gpioa);  	stm_afr_set(&stm_gpioa, 14, STM_AFR_AF1);  	stm_afr_set(&stm_gpioa, 15, STM_AFR_AF1);  #   if USE_SERIAL_2_FLOW @@ -484,10 +465,7 @@ ao_serial_init(void)  	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN);  	ao_stm_usart2.reg = &stm_usart2; -	ao_usart_init(&ao_stm_usart2); -# if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW -	ao_usart_set_flow(&ao_stm_usart2); -# endif +	ao_usart_init(&ao_stm_usart2, USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW);  	stm_nvic_set_enable(STM_ISR_USART2_POS);  	stm_nvic_set_priority(STM_ISR_USART2_POS, 4); diff --git a/src/stmf0/ao_storage_stm.c b/src/stmf0/ao_storage_stm.c new file mode 100644 index 00000000..1a6198a7 --- /dev/null +++ b/src/stmf0/ao_storage_stm.c @@ -0,0 +1,191 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +#include <ao.h> +#include <ao_storage.h> + +uint32_t	ao_storage_block; +ao_pos_t	ao_storage_total; +uint16_t	ao_storage_unit; + +/* Note that the HSI clock must be running for this code to work. + * Also, special care must be taken with the linker to ensure that the + * functions marked 'ramtext' land in ram and not rom. An example of that + * can be found in altos-loader.ld + */ + +static uint8_t +ao_flash_is_locked(void) +{ +	return (stm_flash.cr & (1 << STM_FLASH_CR_LOCK)) != 0; +} + +static void +ao_flash_unlock(void) +{ +	if (!ao_flash_is_locked()) +		return; + +	/* Unlock FLASH_CR register */ +	stm_flash.keyr = STM_FLASH_KEYR_KEY1; +	stm_flash.keyr = STM_FLASH_KEYR_KEY2; +	if (ao_flash_is_locked()) +		ao_panic(AO_PANIC_FLASH); +} + +static void +ao_flash_lock(void) +{ +	stm_flash.cr |= (1 << STM_FLASH_CR_LOCK); +} + +static uint32_t +stm_flash_page_size(void) +{ +	uint16_t	dev_id = stm_dev_id(); + +	switch (dev_id) { +	case 0x440:	/* stm32f05x */ +	case 0x444:	/* stm32f03x */ +	case 0x445:	/* stm32f04x */ +		return 1024; +	case 0x442:	/* stm32f09x */ +	case 0x448:	/* stm32f07x */ +		return 2048; +	} +	ao_panic(AO_PANIC_FLASH); +	return 0; +} + +#define ao_flash_wait_bsy() do { while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)); } while (0) + +static void __attribute__ ((section(".ramtext"),noinline)) +_ao_flash_erase_page(uint16_t *page) +{ +	stm_flash.cr |= (1 << STM_FLASH_CR_PER); + +	stm_flash.ar = (uintptr_t) page; + +	stm_flash.cr |= (1 << STM_FLASH_CR_STRT); + +	ao_flash_wait_bsy(); + +	stm_flash.cr &= ~(1 << STM_FLASH_CR_PER); +} + +#define _ao_flash_addr(pos)	((uint16_t *) (void *) ((uint8_t *) __flash__ + (pos))) + +static void __attribute ((section(".ramtext"), noinline)) _ao_flash_byte(uint32_t pos, uint8_t b) +{ +	uint16_t	v; +	uint16_t	*a = _ao_flash_addr(pos & ~1); + +	if (pos & 1) +		v = (*a & 0xff) | (b << 8); +	else +		v = (*a & 0xff00) | b; +	*a = v; +	ao_flash_wait_bsy(); +} + +static void __attribute__ ((section(".ramtext"), noinline)) +_ao_flash_write(uint32_t pos, void *sv, uint16_t len) +{ +	uint8_t		*s = sv; +	uint16_t	*f16; +	uint16_t	v; + +	stm_flash.cr |= (1 << STM_FLASH_CR_PG); + +	if (pos & 1) { +		_ao_flash_byte(pos++, *s++); +		len--; +	} +	f16 = _ao_flash_addr(pos); +	while(len > 1) { +		v = s[0] | (s[1] << 8); +		s += 2; +		*f16++ = v; +		ao_flash_wait_bsy(); +		len -= 2; +		pos += 2; +	} +	if (len) +		_ao_flash_byte(pos, *s++); + +	stm_flash.cr &= ~(1 << STM_FLASH_CR_PG); +} + +uint8_t +ao_storage_erase(uint32_t pos) +{ +	ao_arch_block_interrupts(); +	ao_flash_unlock(); + +	_ao_flash_erase_page(_ao_flash_addr(pos)); + +	ao_flash_lock(); +	ao_arch_release_interrupts(); +	return 1; +} + +uint8_t +ao_storage_device_write(uint32_t pos, void *v, uint16_t len) +{ +	if (len == 0) +		return 1; + +	ao_arch_block_interrupts(); +	ao_flash_unlock(); + +	_ao_flash_write(pos, v, len); + +	ao_flash_lock(); +	ao_arch_release_interrupts(); +	return 1; +} + +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_flash_addr(pos), len); +	return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +	ao_storage_block = stm_flash_page_size(); +	ao_storage_total = ((uint8_t *) __flash_end__) - ((uint8_t *) __flash__); +	ao_storage_unit = ao_storage_total; +} + +void +ao_storage_device_info(void) __reentrant +{ +	printf ("Using internal flash, page %d bytes, total %d bytes\n", +		ao_storage_block, ao_storage_total); +} + +void +ao_storage_device_init(void) +{ +} diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c index 5c05e4f1..50fd67b8 100644 --- a/src/stmf0/ao_timer.c +++ b/src/stmf0/ao_timer.c @@ -86,6 +86,7 @@ ao_timer_set_adc_interval(uint8_t interval)  void  ao_timer_init(void)  { +	stm_systick.csr = 0;  	stm_systick.rvr = SYSTICK_RELOAD;  	stm_systick.cvr = 0;  	stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) | diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index 652b3b6c..59aed3aa 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -655,7 +655,7 @@ ao_usb_ep0_in_start(uint16_t max)  	ao_usb_ep0_flush();  } -static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; +struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};  #if AO_USB_DEVICE_ID_SERIAL  static uint8_t ao_usb_serial[2 + 48]; diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index e53a5dfd..61faf2e4 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -282,8 +282,8 @@ struct stm_rcc {  extern struct stm_rcc stm_rcc; -/* Nominal high speed internal oscillator frequency is 16MHz */ -#define STM_HSI_FREQ		16000000 +/* Nominal high speed internal oscillator frequency is 8MHz */ +#define STM_HSI_FREQ		8000000  #define STM_RCC_CR_PLLRDY	(25)  #define STM_RCC_CR_PLLON	(24) diff --git a/src/telebt-v3.0/Makefile b/src/telebt-v3.0/Makefile index 40d1f6e4..4636c046 100644 --- a/src/telebt-v3.0/Makefile +++ b/src/telebt-v3.0/Makefile @@ -55,6 +55,7 @@ ALTOS_SRC = \  	ao_convert_volt.c \  	ao_packet_master.c \  	ao_packet.c \ +	ao_send_packet.c \  	ao_monitor.c \  	$(PROFILE) \  	$(SAMPLE_PROFILE) \ diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c index 8775d993..63633c90 100644 --- a/src/telebt-v3.0/ao_telebt.c +++ b/src/telebt-v3.0/ao_telebt.c @@ -23,6 +23,7 @@  #include <ao_profile.h>  #include <ao_btm.h>  #include <ao_lco_cmd.h> +#include <ao_send_packet.h>  #if HAS_SAMPLE_PROFILE  #include <ao_sample_profile.h>  #endif @@ -53,6 +54,7 @@ main(void)  	ao_radio_init();  	ao_packet_master_init();  	ao_monitor_init(); +	ao_send_packet_init();  	ao_config_init(); diff --git a/src/telebt-v4.0/.gitignore b/src/telebt-v4.0/.gitignore new file mode 100644 index 00000000..d1cf2326 --- /dev/null +++ b/src/telebt-v4.0/.gitignore @@ -0,0 +1,4 @@ +ao_product.h +*.bin +*.ihx +*.elf diff --git a/src/telebt-v4.0/Makefile b/src/telebt-v4.0/Makefile new file mode 100644 index 00000000..38ac7513 --- /dev/null +++ b/src/telebt-v4.0/Makefile @@ -0,0 +1,81 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_boot.h \ +	ao_pins.h \ +	ao_product.h \ +	ao_cc1200_CC1200.h \ +	ao_task.h \ +	ao_rn4678.h \ +	stm32f0.h \ +	Makefile + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_config.c \ +	ao_data.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_serial_stm.c \ +	ao_rn4678.c \ +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_cc1200.c \ +	ao_adc_stm.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_convert_volt.c \ +	ao_packet_master.c \ +	ao_packet.c \ +	ao_monitor.c \ +	ao_send_packet.c + +PRODUCT=TeleBT-v4.0 +PRODUCT_DEF=-DTELEBT_V_4_0 +IDPRODUCT=0x000e + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g + +PROGNAME=telebt-v4.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telebt.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telebt-v4.0/ao_pins.h b/src/telebt-v4.0/ao_pins.h new file mode 100644 index 00000000..f3d70d1a --- /dev/null +++ b/src/telebt-v4.0/ao_pins.h @@ -0,0 +1,290 @@ +/* + * Copyright © 2017 Bdale Garbee <bdale@gag.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define AO_STACK_SIZE		512 + +#define AO_HSE                  32000000 +#define AO_RCC_CFGR_PLLMUL	STM_RCC_CFGR_PLLMUL_3 +#define AO_RCC_CFGR2_PLLDIV	STM_RCC_CFGR2_PREDIV_2 +#define AO_PLLMUL		3 +#define AO_PLLDIV		2 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER        1 +#define AO_RCC_CFGR_HPRE_DIV    STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER        1 +#define AO_RCC_CFGR_PPRE_DIV    STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB			1 +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	0 + +#define IS_FLASH_LOADER 	0 +#define HAS_TASK_QUEUE		1 + +/* + * Serial ports + */ +#define HAS_SERIAL_1		0 +#define USE_SERIAL_1_STDIN	0 +#define SERIAL_1_PB6_PB7	0 +#define SERIAL_1_PA9_PA10	0 + +#define HAS_SERIAL_2		1 +#define USE_SERIAL_2_STDIN	1 +#define DELAY_SERIAL_2_STDIN	1 +#define USE_SERIAL_2_FLOW	1 +#define USE_SERIAL_2_SW_FLOW	0 +#define SERIAL_2_PA2_PA3	1 +#define SERIAL_2_PD5_PD6	0 +#define SERIAL_2_PORT_RTS	(&stm_gpioa) +#define SERIAL_2_PIN_RTS	1 +#define SERIAL_2_PORT_CTS	(&stm_gpioa) +#define SERIAL_2_PIN_CTS	0 + +#define AO_CONFIG_MAX_SIZE	1024 + +#define HAS_EEPROM		0 +#define USE_INTERNAL_FLASH	0 +#define USE_EEPROM_CONFIG	0 +#define USE_STORAGE_CONFIG	0 +#define HAS_BEEP		0 +#define HAS_BATTERY_REPORT	0 +#define HAS_RADIO		1 +#define HAS_TELEMETRY		0 +#define HAS_APRS		0 +#define HAS_ACCEL		0 +#define HAS_AES			0 + +#define HAS_SPI_1		1 +#define SPI_1_PA5_PA6_PA7	1	/* CC1200 */ +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_PE13_PE14_PE15	0 +#define SPI_1_OSPEEDR		STM_OSPEEDR_HIGH + +#define HAS_SPI_2		0 +#define SPI_2_PB13_PB14_PB15	0 +#define SPI_2_PD1_PD3_PD4	0 +#define SPI_2_OSPEEDR		STM_OSPEEDR_HIGH + +#define HAS_I2C_1		0 +#define I2C_1_PB8_PB9		0 + +#define HAS_I2C_2		0 +#define I2C_2_PB10_PB11		0 + +#define PACKET_HAS_SLAVE	0 +#define PACKET_HAS_MASTER	1 + +#define LOW_LEVEL_DEBUG		0 + +#define LED_PORT_0_ENABLE	STM_RCC_AHBENR_IOPBEN +#define LED_PORT_1_ENABLE	STM_RCC_AHBENR_IOPCEN +#define LED_PORT_0		(&stm_gpiob) +#define LED_PORT_1		(&stm_gpioc) +#define LED_PORT_0_SHIFT	0 +#define LED_PORT_1_SHIFT	0 +#define LED_PIN_RED		(0 + LED_PORT_0_SHIFT) +#define LED_PIN_BLUE		(15 + LED_PORT_1_SHIFT) +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_BLUE		(1 << LED_PIN_BLUE) +#define LED_PORT_0_MASK		(AO_LED_RED) +#define LED_PORT_1_MASK		(AO_LED_BLUE) +#define AO_BT_LED		AO_LED_BLUE + +#define LEDS_AVAILABLE		(AO_LED_RED | AO_LED_BLUE) + +#define HAS_GPS			0 +#define HAS_FLIGHT		0 +#define HAS_ADC			1 +#define HAS_ADC_TEMP		0 +#define HAS_LOG			0 + +/* + * ADC + */ +#define AO_DATA_RING		32 +#define AO_ADC_NUM_SENSE	2 + +struct ao_adc { +	int16_t			v_batt; +}; + +#define AO_ADC_DUMP(p) \ +	printf("tick: %5u batt %5d\n", \ +	       (p)->tick, \ +	       (p)->adc.v_batt); + +#define AO_ADC_V_BATT		4 +#define AO_ADC_V_BATT_PORT	(&stm_gpioa) +#define AO_ADC_V_BATT_PIN	4 + +#define AO_ADC_RCC_AHBENR	((1 << STM_RCC_AHBENR_IOPAEN)) + +#define AO_NUM_ADC_PIN		1 + +#define AO_ADC_PIN0_PORT	AO_ADC_V_BATT_PORT +#define AO_ADC_PIN0_PIN		AO_ADC_V_BATT_PIN +#define AO_ADC_PIN0_CH		AO_ADC_V_BATT_PIN + +#define AO_NUM_ADC	       	(AO_NUM_ADC_PIN) + +#define AO_ADC_SQ1		AO_ADC_V_BATT + +/* + * Voltage divider on ADC battery sampler + */ +#define AO_BATTERY_DIV_PLUS	51	/* 5.1k */ +#define AO_BATTERY_DIV_MINUS	100	/* 10k */ + +/* + * ADC reference in decivolts + */ +#define AO_ADC_REFERENCE_DV	33 + +/* + * RN4678 + */ +#define HAS_RN			1 + +#define ao_serial_rn_getchar	ao_serial2_getchar +#define ao_serial_rn_putchar	ao_serial2_putchar +#define _ao_serial_rn_pollchar	_ao_serial2_pollchar +#define _ao_serial_rn_sleep_for	_ao_serial2_sleep_for +#define ao_serial_rn_set_speed ao_serial2_set_speed +#define ao_serial_rn_drain	ao_serial2_drain +#define ao_serial_rn_rx_fifo	(ao_stm_usart2.rx_fifo) + +/* Pin 5. BM70 P2_2 */ +#define AO_RN_SW_BTN_PORT	(&stm_gpioc) +#define AO_RN_SW_BTN_PIN	14 + +/* Pin 9. BM70 P2_3 */ +#define AO_RN_WAKEUP_PORT	(&stm_gpiob) +#define AO_RN_WAKEUP_PIN	9 + +/* Pin 11. BM70 P2_7/tx_ind. Status indication along with P1_5 */ +#define AO_RN_P0_4_PORT		(&stm_gpioc) +#define AO_RN_P0_4_PIN		13 + +/* Pin 12. BM70 P1_1. Status indication along with P0_4 */ +#define AO_RN_P1_5_PORT		(&stm_gpiob) +#define AO_RN_P1_5_PIN		6 + +/* Pin 13. BM70 P1_2. Also I2C SCL */ +#define AO_RN_P1_2_PORT		(&stm_gpiob) +#define AO_RN_P1_2_PIN		7 + +/* Pin 14. BM70 P1_3. Also I2C SDA */ +#define AO_RN_P1_3_PORT		(&stm_gpiob) +#define AO_RN_P1_3_PIN		8 + +/* Pin 15. BM70 P0_0/cts. */ +#define AO_RN_CTS_PORT		(&stm_gpioa) +#define AO_RN_CTS_PIN		1 + +/* Pin 16. BM70 P1_0. */ +#define AO_RN_P0_5_PORT		(&stm_gpiob) +#define AO_RN_P0_5_PIN		5 + +/* Pin 17. BM70 P3_6. */ +#define AO_RN_RTS_PORT		(&stm_gpioa) +#define AO_RN_RTS_PIN		0 + +/* Pin 18. BM70 P2_0. */ +#define AO_RN_P2_0_PORT		(&stm_gpiob) +#define AO_RN_P2_0_PIN		3 + +/* Pin 19. BM70 P2_4. */ +#define AO_RN_P2_4_PORT		(&stm_gpioa) +#define AO_RN_P2_4_PIN		10 + +/* Pin 20. BM70 NC. */ +#define AO_RN_EAN_PORT +#define AO_RN_EAN_PIN + +/* Pin 21. BM70 RST_N. */ +#define AO_RN_RST_N_PORT	(&stm_gpioa) +#define AO_RN_RST_N_PIN		15 + +/* Pin 22. BM70 RXD. */ +#define AO_RN_RXD_PORT		(&stm_gpioa) +#define AO_RN_RXD_PIN		2 + +/* Pin 23. BM70 TXD. */ +#define AO_RN_TXD_PORT		(&stm_gpioa) +#define AO_RN_TXD_PIN		3 + +/* Pin 24. BM70 P3_1/RSSI_IND. */ +#define AO_RN_P3_1_PORT		(&stm_gpiob) +#define AO_RN_P3_1_PIN		2 + +/* Pin 25. BM70 P3_2/LINK_DROP. */ +#define AO_RN_P3_2_PORT		(&stm_gpioa) +#define AO_RN_P3_2_PIN		8 + +/* Pin 26. BM70 P3_3/UART_RX_IND. */ +#define AO_RN_P3_3_PORT		(&stm_gpiob) +#define AO_RN_P3_3_PIN		15 + +/* Pin 27. BM70 P3_4/PAIRING_KEY. */ +#define AO_RN_P3_4_PORT		(&stm_gpiob) +#define AO_RN_P3_4_PIN		14 + +/* Pin 28. BM70 P3_5. */ +#define AO_RN_P3_6_PORT		(&stm_gpiob) +#define AO_RN_P3_6_PIN		13 + +/* Pin 29. BM70 P0_7. */ +#define AO_RN_P3_7_PORT		(&stm_gpiob) +#define AO_RN_P3_7_PIN		12 + +/* + * Radio (cc1200) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 	5695485 + +#define AO_FEC_DEBUG		0 +#define AO_CC1200_SPI_CS_PORT	(&stm_gpiob) +#define AO_CC1200_SPI_CS_PIN	11 +#define AO_CC1200_SPI_BUS	AO_SPI_1_PA5_PA6_PA7 +#define AO_CC1200_SPI		stm_spi1 +#define AO_CC1200_SPI_SPEED	AO_SPI_SPEED_6MHz + +#define AO_CC1200_INT_PORT		(&stm_gpiob) +#define AO_CC1200_INT_PIN		(10) + +#define AO_CC1200_INT_GPIO	2 +#define AO_CC1200_INT_GPIO_IOCFG	CC1200_IOCFG2 + +#define HAS_BOOT_RADIO		0 + +/* Monitor bits */ +#define HAS_MONITOR		1 +#define LEGACY_MONITOR		0 +#define AO_MONITOR_LED		AO_LED_RED + +#endif /* _AO_PINS_H_ */ diff --git a/src/telebt-v4.0/ao_telebt.c b/src/telebt-v4.0/ao_telebt.c new file mode 100644 index 00000000..953ec4bc --- /dev/null +++ b/src/telebt-v4.0/ao_telebt.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2015 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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 <ao.h> +#include <ao_exti.h> +#include <ao_packet.h> +#include <ao_send_packet.h> +#include <ao_usb.h> +#include <ao_rn4678.h> + +int +main(void) +{ +	ao_clock_init(); + +	ao_task_init(); +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(LEDS_AVAILABLE); +	ao_timer_init(); + +	ao_spi_init(); +	ao_dma_init(); +	ao_exti_init(); + +	ao_adc_init(); +	ao_cmd_init(); +	ao_send_packet_init(); + +	ao_usb_init(); +	ao_serial_init(); + +	ao_radio_init(); +	ao_packet_master_init(); +	ao_monitor_init(); +	ao_rn4678_init(); + +	ao_config_init(); + +	ao_led_off(LEDS_AVAILABLE); + +	ao_start_scheduler(); +	return 0; +} diff --git a/src/telebt-v4.0/flash-loader/Makefile b/src/telebt-v4.0/flash-loader/Makefile new file mode 100644 index 00000000..1a3c8c49 --- /dev/null +++ b/src/telebt-v4.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telebt-v4.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/telebt-v4.0/flash-loader/ao_pins.h b/src/telebt-v4.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..8f4d6f81 --- /dev/null +++ b/src/telebt-v4.0/flash-loader/ao_pins.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include <ao_flash_stm_pins.h> + +/* ground U7 pin 30 to force bootload */ + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpioa +#define AO_BOOT_APPLICATION_PIN		9 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +/* USB */ +#define HAS_USB			1 +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefiretwo-v1.0/Makefile b/src/telefireone-v1.0/Makefile index 87d5d477..53f088cb 100644 --- a/src/telefiretwo-v1.0/Makefile +++ b/src/telefireone-v1.0/Makefile @@ -55,18 +55,18 @@ ALTOS_SRC = \  	ao_pad.c \  	ao_radio_cmac_cmd.c \  	ao_log.c \ -	ao_log_firetwo.c +	ao_log_fireone.c  PRODUCT_SRC = \ -	ao_telefiretwo.c +	ao_telefireone.c -PRODUCT=TeleFireTwo-v1.0 -PRODUCT_DEF=-DTELEFIRETWO_V_1_0 +PRODUCT=TeleFireOne-v1.0 +PRODUCT_DEF=-DTELEFIREONE_V_1_0  IDPRODUCT=0x000f  CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g -PROGNAME = telefiretwo-v1.0 +PROGNAME = telefireone-v1.0  PROG = $(PROGNAME)-$(VERSION).elf  HEX = $(PROGNAME)-$(VERSION).ihx diff --git a/src/telefiretwo-v1.0/ao_pins.h b/src/telefireone-v1.0/ao_pins.h index b2f5a5ab..d36d9d82 100644 --- a/src/telefiretwo-v1.0/ao_pins.h +++ b/src/telefireone-v1.0/ao_pins.h @@ -34,7 +34,7 @@  #define HAS_EEPROM		1  #define HAS_LOG			1  #define HAS_PAD			1 -#define USE_INTERNAL_FLASH	0 +#define USE_INTERNAL_FLASH	1  #define IGNITE_ON_P0		0  #define PACKET_HAS_MASTER	0  #define PACKET_HAS_SLAVE	0 diff --git a/src/telefiretwo-v1.0/ao_telefiretwo.c b/src/telefireone-v1.0/ao_telefireone.c index 115b3e91..115b3e91 100644 --- a/src/telefiretwo-v1.0/ao_telefiretwo.c +++ b/src/telefireone-v1.0/ao_telefireone.c diff --git a/src/telefiretwo-v1.0/flash-loader/.gitignore b/src/telefireone-v1.0/flash-loader/.gitignore index 65fe7eab..65fe7eab 100644 --- a/src/telefiretwo-v1.0/flash-loader/.gitignore +++ b/src/telefireone-v1.0/flash-loader/.gitignore diff --git a/src/telefiretwo-v1.0/flash-loader/Makefile b/src/telefireone-v1.0/flash-loader/Makefile index d429dcc4..d429dcc4 100644 --- a/src/telefiretwo-v1.0/flash-loader/Makefile +++ b/src/telefireone-v1.0/flash-loader/Makefile diff --git a/src/telefiretwo-v1.0/flash-loader/ao_pins.h b/src/telefireone-v1.0/flash-loader/ao_pins.h index ded45a40..ded45a40 100644 --- a/src/telefiretwo-v1.0/flash-loader/ao_pins.h +++ b/src/telefireone-v1.0/flash-loader/ao_pins.h diff --git a/src/telegps-v2.0/.gitignore b/src/telegps-v2.0/.gitignore new file mode 100644 index 00000000..892c3acc --- /dev/null +++ b/src/telegps-v2.0/.gitignore @@ -0,0 +1,3 @@ +ao_product.h +ao_serial_lpc.h +*.elf diff --git a/src/telegps-v2.0/ao_pins.h b/src/telegps-v2.0/ao_pins.h index c51f0afb..f92564d6 100644 --- a/src/telegps-v2.0/ao_pins.h +++ b/src/telegps-v2.0/ao_pins.h @@ -21,18 +21,23 @@  #define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN  #define LED_PORT        (&stm_gpiob) -#define LED_PIN_RED     5 -#define AO_LED_RED      (1 << LED_PIN_RED) +#define LED_PIN_GREEN   5 +#define AO_LED_GREEN    (1 << LED_PIN_GREEN) +#define AO_LED_PANIC	AO_LED_GREEN +#define AO_LED_GPS_LOCK	AO_LED_GREEN -#define LEDS_AVAILABLE  (AO_LED_RED) +#define LEDS_AVAILABLE  (AO_LED_GREEN) + +#define AO_STACK_SIZE		512  #define IS_FLASH_LOADER		0  #define HAS_BEEP 	       0  #define AO_HSE                  32000000  #define AO_RCC_CFGR_PLLMUL      STM_RCC_CFGR_PLLMUL_3 +#define AO_RCC_CFGR2_PLLDIV	STM_RCC_CFGR2_PREDIV_2  #define AO_PLLMUL               3 -#define AO_PLLDIV               1 +#define AO_PLLDIV               2  /* HCLK = 48MHz */  #define AO_AHB_PRESCALER        1 @@ -42,8 +47,6 @@  #define AO_APB_PRESCALER        1  #define AO_RCC_CFGR_PPRE_DIV    STM_RCC_CFGR_PPRE_DIV_1 -#define AO_RCC_CFGR2_PLLDIV	STM_RCC_CFGR2_PREDIV_1 -  #define HAS_USB                         1  #define AO_USB_DIRECTIO                 0  #define AO_PA11_PA12_RMP                1 @@ -53,11 +56,13 @@  /* ADC */  #define HAS_ADC			1 -#define AO_ADC_PIN0_PORT        (&stm_gpioa) -#define AO_ADC_PIN0_PIN         0 -#define AO_ADC_PIN0_CH          0 +#define AO_ADC_PIN0_PORT        (&stm_gpiob) +#define AO_ADC_PIN0_PIN         1 +#define AO_ADC_PIN0_CH          9 + +#define AO_ADC_RCC_AHBENR       ((1 << STM_RCC_AHBENR_IOPBEN)) -#define AO_ADC_RCC_AHBENR       ((1 << STM_RCC_AHBENR_IOPAEN)) +#define ao_telemetry_battery_convert(a)	((a) << 3)  #define AO_NUM_ADC              1 @@ -90,8 +95,6 @@ struct ao_adc {  #define SPI_1_PB3_PB4_PB5       0  #define SPI_1_OSPEEDR           STM_OSPEEDR_HIGH -#define HAS_MS5607              0 -  /* Flash */  #define M25_MAX_CHIPS           1 @@ -99,14 +102,18 @@ struct ao_adc {  #define AO_M25_SPI_CS_MASK      (1 << 0)  #define AO_M25_SPI_BUS          AO_SPI_1_PA5_PA6_PA7 -#define HAS_SERIAL_1		1 +/* Serial */ +#define HAS_SERIAL_1		0  #define SERIAL_1_PB6_PB7	1  #define USE_SERIAL_1_STDIN	0 -#define ao_gps_getchar		ao_serial1_getchar -#define ao_gps_putchar		ao_serial1_putchar -#define ao_gps_set_speed	ao_serial1_set_speed -#define ao_gps_fifo		(ao_usart_rx_fifo) +#define HAS_SERIAL_2	       	1 +#define SERIAL_2_PA2_PA3	1 +#define USE_SERIAL_2_STDIN	0 + +#define ao_gps_getchar		ao_serial2_getchar +#define ao_gps_putchar		ao_serial2_putchar +#define ao_gps_set_speed	ao_serial2_set_speed  #define HAS_EEPROM		1  #define USE_INTERNAL_FLASH	0 @@ -114,7 +121,6 @@ struct ao_adc {  #define HAS_TELEMETRY		1  #define HAS_RDF			1  #define HAS_APRS		1 -#define HAS_RADIO_RECV		0  #define HAS_GPS			1  #define HAS_FLIGHT		0 @@ -143,22 +149,17 @@ struct ao_adc {  #define AO_FEC_DEBUG            0  #define AO_CC1200_SPI_CS_PORT   (&stm_gpioa) -#define AO_CC1200_SPI_CS_PIN    5 +#define AO_CC1200_SPI_CS_PIN    1  #define AO_CC1200_SPI_BUS       AO_SPI_1_PA5_PA6_PA7  #define AO_CC1200_SPI           stm_spi1 -#define AO_CC1200_SPI_SPEED     AO_SPI_SPEED_FAST +#define AO_CC1200_SPI_SPEED     AO_SPI_SPEED_6MHz  #define AO_CC1200_INT_PORT              (&stm_gpioa)  #define AO_CC1200_INT_PIN               4 -#define AO_CC1200_MCU_WAKEUP_PORT       (&stm_gpioa) -#define AO_CC1200_MCU_WAKEUP_PIN        (0)  #define AO_CC1200_INT_GPIO      2  #define AO_CC1200_INT_GPIO_IOCFG        CC1200_IOCFG2 -#define AO_CC1200_MARC_GPIO     3 -#define AO_CC1200_MARC_GPIO_IOCFG       CC1200_IOCFG3 -  #define HAS_BOOT_RADIO          0  #endif /* _AO_PINS_H_ */ diff --git a/src/telegps-v2.0/ao_telegps.c b/src/telegps-v2.0/ao_telegps.c index 7a923d11..998c2008 100644 --- a/src/telegps-v2.0/ao_telegps.c +++ b/src/telegps-v2.0/ao_telegps.c @@ -25,43 +25,35 @@ int  main(void)  {  	ao_clock_init(); +	ao_task_init(); +	ao_cmd_init(); +	ao_config_init(); -#if HAS_STACK_GUARD -	ao_mpu_init(); -#endif +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(AO_LED_GREEN); -	ao_task_init(); +	/* internal systems */  	ao_timer_init(); - -	ao_spi_init(); +	ao_dma_init();  	ao_exti_init(); -	ao_storage_init(); - +	/* SoC hardware */ +	ao_adc_init();  	ao_serial_init(); - -	ao_cmd_init(); - +	ao_spi_init();  	ao_usb_init(); -	ao_radio_init(); - -#if HAS_ADC -	ao_adc_init(); -#endif +	/* External hardware */ +	ao_storage_init(); +	ao_radio_init();  	ao_gps_init(); -#if HAS_LOG -	ao_log_init(); -#endif - -	ao_tracker_init(); +	/* Services */ +	ao_log_init();  	ao_telemetry_init(); +	ao_tracker_init(); -#if HAS_SAMPLE_PROFILE -	ao_sample_profile_init(); -#endif -	ao_config_init(); +	ao_led_off(AO_LED_GREEN);  	ao_start_scheduler();  	return 0; diff --git a/src/telegps-v2.0/flash-loader/.gitignore b/src/telegps-v2.0/flash-loader/.gitignore new file mode 100644 index 00000000..7bbed045 --- /dev/null +++ b/src/telegps-v2.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +*.elf +*.bin diff --git a/src/telemini-v2.0/ao_telemini.c b/src/telemini-v2.0/ao_telemini.c index 68bc3dfe..a9ee423c 100644 --- a/src/telemini-v2.0/ao_telemini.c +++ b/src/telemini-v2.0/ao_telemini.c @@ -20,8 +20,6 @@  #include "ao_pins.h"  #include <ao_exti.h> -__xdata uint8_t ao_force_freq; -  void  main(void)  { diff --git a/src/telemini-v3.0/.gitignore b/src/telemini-v3.0/.gitignore new file mode 100644 index 00000000..57946eb5 --- /dev/null +++ b/src/telemini-v3.0/.gitignore @@ -0,0 +1,3 @@ +ao_product.h +*.bin +*.elf diff --git a/src/telemini-v3.0/ao_pins.h b/src/telemini-v3.0/ao_pins.h index 351d28d8..17cff2ae 100644 --- a/src/telemini-v3.0/ao_pins.h +++ b/src/telemini-v3.0/ao_pins.h @@ -1,9 +1,10 @@  /* - * Copyright © 2013 Keith Packard <keithp@keithp.com> + * Copyright © 2017 Keith Packard <keithp@keithp.com>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * 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 @@ -66,6 +67,13 @@  #define HAS_IGNITE_REPORT	1  #define AO_SMALL_ALTITUDE_TABLE	1 +/* Use debug connector clock for recovery mode */ +#define HAS_FORCE_FREQ		1 +#define AO_RECOVERY_PORT	(&stm_gpioa) +#define AO_RECOVERY_PIN		14 +#define AO_RECOVERY_VALUE	0 +#define AO_RECOVERY_MODE	AO_EXTI_MODE_PULL_UP +  /* Beeper is on Tim1 CH3 */  #define BEEPER_CHANNEL		4  #define BEEPER_TIMER		2 diff --git a/src/telemini-v3.0/ao_telemini.c b/src/telemini-v3.0/ao_telemini.c index 82c1acd4..a50268b9 100644 --- a/src/telemini-v3.0/ao_telemini.c +++ b/src/telemini-v3.0/ao_telemini.c @@ -1,9 +1,10 @@  /* - * Copyright © 2011 Keith Packard <keithp@keithp.com> + * Copyright © 2017 Keith Packard <keithp@keithp.com>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * 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 @@ -18,9 +19,26 @@  #include <ao.h>  #include <ao_exti.h> +static void +ao_check_recovery(void) +{ +	int	i; +	ao_enable_input(AO_RECOVERY_PORT, AO_RECOVERY_PIN, AO_RECOVERY_MODE); +	for (i = 0; i < 100; i++) +		ao_arch_nop(); +	if (ao_gpio_get(AO_RECOVERY_PORT, AO_RECOVERY_PIN, AO_RECOVERY) == AO_RECOVERY_VALUE) { +		ao_flight_force_idle = 1; +		ao_force_freq = 1; +	} +	ao_gpio_set_mode(AO_RECOVERY_PORT, AO_RECOVERY_PIN, 0); +	ao_disable_port(AO_RECOVERY_PORT); +} +  void  main(void)  { +	ao_check_recovery(); +  	ao_clock_init();  	ao_task_init();  	ao_timer_init(); diff --git a/src/telemini-v3.0/flash-loader/ao_pins.h b/src/telemini-v3.0/flash-loader/ao_pins.h index fea9a645..c523d413 100644 --- a/src/telemini-v3.0/flash-loader/ao_pins.h +++ b/src/telemini-v3.0/flash-loader/ao_pins.h @@ -21,13 +21,13 @@  #include <ao_flash_stm_pins.h> -/* beeper to 3.3V for boot loader mode */ +/* SWDIO to gnd for boot loader mode */  #define AO_BOOT_PIN			1  #define AO_BOOT_APPLICATION_GPIO	stm_gpioa -#define AO_BOOT_APPLICATION_PIN		3 -#define AO_BOOT_APPLICATION_VALUE	0 -#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_DOWN +#define AO_BOOT_APPLICATION_PIN		13 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP  /* USB */  #define HAS_USB			1 diff --git a/src/test/.gitignore b/src/test/.gitignore index 9237780b..56f532ef 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -18,3 +18,4 @@ ao_flight_test_noisy_accel  ao_flight_test_metrum  ao_micropeak_test  ao_aes_test +ao_lisp_test diff --git a/src/test/Makefile b/src/test/Makefile index a22abe46..a0c2d5fe 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,7 +1,7 @@  vpath % ..:../kernel:../drivers:../util:../micropeak:../aes:../product:../lisp  PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ -	ao_flight_test_metrum \ +	ao_flight_test_metrum ao_flight_test_mini \  	ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \  	ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \  	ao_ms5607_convert_test ao_quaternion_test ao_lisp_test @@ -37,6 +37,9 @@ ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.  ao_flight_test_metrum: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)  	cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $< -lm +ao_flight_test_mini: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS) +	cc -DEASYMINI=1 -DHAS_ACCEL=0 $(CFLAGS) -o $@ $< -lm +  ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h  	cc $(CFLAGS) -o $@ $< diff --git a/src/test/ao_aes_test.c b/src/test/ao_aes_test.c index 4b65df8d..135c6f1a 100644 --- a/src/test/ao_aes_test.c +++ b/src/test/ao_aes_test.c @@ -30,7 +30,7 @@  #include "../aes/ao_aes_tables.c"  #include "../aes/ao_aes.c" -static uint8_t key[16]; +static uint8_t my_key[64];  static uint8_t text[16];  static uint8_t cbc[16]; @@ -41,7 +41,7 @@ main (int argc, char **argv)  	ao_aes_init();  	ao_aes_set_mode(ao_aes_mode_cbc_mac); -	ao_aes_set_key(key); +	ao_aes_set_key(my_key);  	ao_aes_zero_iv();  	ao_aes_run(text, cbc); diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 25ddb48f..d3d39f2a 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -46,7 +46,7 @@  int ao_gps_new; -#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) +#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) && !defined(EASYMINI)  #define TELEMETRUM_V1 1  #endif @@ -84,6 +84,18 @@ struct ao_adc {  };  #endif +#if EASYMINI +#define AO_ADC_NUM_SENSE	2 +#define HAS_MS5607		1 +#define HAS_BEEP		1 +#define AO_CONFIG_MAX_SIZE	1024 + +struct ao_adc { +	int16_t			sense_a; +	int16_t			sense_m; +	int16_t			v_batt; +}; +#endif  #if TELEMETRUM_V1  /* @@ -323,7 +335,7 @@ struct ao_cmds {  #define ao_xmemcmp(d,s,c) memcmp(d,s,c)  #define AO_NEED_ALTITUDE_TO_PRES 1 -#if TELEMEGA || TELEMETRUM_V2 +#if TELEMEGA || TELEMETRUM_V2 || EASYMINI  #include "ao_convert_pa.c"  #include <ao_ms5607.h>  struct ao_ms5607_prom	ao_ms5607_prom; @@ -475,7 +487,7 @@ ao_insert(void)  #else  		double	accel = 0.0;  #endif -#if TELEMEGA || TELEMETRUM_V2 +#if TELEMEGA || TELEMETRUM_V2 || EASYMINI  		double	height;  		ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked); @@ -670,6 +682,19 @@ int32(uint8_t *bytes, int off)  	return (int32_t) uint32(bytes, off);  } +uint32_t +uint24(uint8_t *bytes, int off) +{ +	return (uint32_t) bytes[off] | (((uint32_t) bytes[off+1]) << 8) | +		(((uint32_t) bytes[off+2]) << 16); +} + +int32_t +int24(uint8_t *bytes, int off) +{ +	return (int32_t) uint24(bytes, off); +} +  static int log_format;  void @@ -694,12 +719,14 @@ ao_sleep(void *wchan)  		for (;;) {  			if (ao_records_read > 2 && ao_flight_state == ao_flight_startup)  			{ +  #if TELEMEGA  				ao_data_static.mpu6000 = ao_ground_mpu6000;  #endif  #if TELEMETRUM_V1  				ao_data_static.adc.accel = ao_flight_ground_accel;  #endif +  				ao_insert();  				return;  			} @@ -829,6 +856,72 @@ ao_sleep(void *wchan)  				}  			}  #endif +#if EASYMINI +			if ((log_format == AO_LOG_FORMAT_EASYMINI1 || log_format == AO_LOG_FORMAT_EASYMINI2) && nword == 14 && strlen(words[0]) == 1) { +				int	i; +				struct ao_ms5607_value	value; + +				type = words[0][0]; +				tick = strtoul(words[1], NULL, 16); +//				printf ("%c %04x", type, tick); +				for (i = 2; i < nword; i++) { +					bytes[i - 2] = strtoul(words[i], NULL, 16); +//					printf(" %02x", bytes[i-2]); +				} +//				printf ("\n"); +				switch (type) { +				case 'F': +					ao_flight_started = 1; +					ao_ground_pres = uint32(bytes, 4); +					ao_ground_height = ao_pa_to_altitude(ao_ground_pres); +#if 0 +					printf("ground pres %d height %d\n", ao_ground_pres, ao_ground_height); +					printf("sens %d off %d tcs %d tco %d tref %d tempsens %d crc %d\n", +					       ao_ms5607_prom.sens, +					       ao_ms5607_prom.off, +					       ao_ms5607_prom.tcs, +					       ao_ms5607_prom.tco, +					       ao_ms5607_prom.tref, +					       ao_ms5607_prom.tempsens, +					       ao_ms5607_prom.crc); +#endif +					break; +				case 'A': +					ao_data_static.tick = tick; +					ao_data_static.ms5607_raw.pres = int24(bytes, 0); +					ao_data_static.ms5607_raw.temp = int24(bytes, 3); +#if 0 +					printf("raw pres %d temp %d\n", +					       ao_data_static.ms5607_raw.pres, +					       ao_data_static.ms5607_raw.temp); +#endif +					ao_ms5607_convert(&ao_data_static.ms5607_raw, &value); +//					printf("pres %d height %d\n", value.pres, ao_pa_to_altitude(value.pres)); +					ao_records_read++; +					ao_insert(); +					return; +				} +				continue; +			} else if (nword == 3 && strcmp(words[0], "ms5607") == 0) { +				if (strcmp(words[1], "reserved:") == 0) +					ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "sens:") == 0) +					ao_ms5607_prom.sens = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "off:") == 0) +					ao_ms5607_prom.off = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "tcs:") == 0) +					ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "tco:") == 0) +					ao_ms5607_prom.tco = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "tref:") == 0) +					ao_ms5607_prom.tref = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "tempsens:") == 0) +					ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "crc:") == 0) +					ao_ms5607_prom.crc = strtoul(words[2], NULL, 10); +				continue; +			} +#endif  #if TELEMETRUM_V2  			if (log_format == AO_LOG_FORMAT_TELEMETRUM && nword == 14 && strlen(words[0]) == 1) {  				int	i; @@ -1007,7 +1100,7 @@ ao_sleep(void *wchan)  			if (type != 'F' && !ao_flight_started)  				continue; -#if TELEMEGA || TELEMETRUM_V2 +#if TELEMEGA || TELEMETRUM_V2 || EASYMINI  			(void) a;  			(void) b;  #else diff --git a/src/test/ao_int64_test.c b/src/test/ao_int64_test.c index 07538ee0..d329f67b 100644 --- a/src/test/ao_int64_test.c +++ b/src/test/ao_int64_test.c @@ -34,7 +34,7 @@ int	errors;  		c = ao_cast64(&ao_r);					\  		if (c != r) {						\  			printf ("trial %4d: %lld " #func mod " %lld = %lld (should be %lld)\n", \ -				trial, (int64_t) (a), (int64_t) b, c, r); \ +				trial, (long long) (a), (long long) b, (long long) c, (long long) r); \  			++errors;					\  		}							\  	} while (0) diff --git a/src/util/make-kalman b/src/util/make-kalman index 580a4515..c630e9cb 100644 --- a/src/util/make-kalman +++ b/src/util/make-kalman @@ -40,4 +40,5 @@ 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 -nickle kalman_micro.5c -p AO_MK_BARO -c baro -t 0.096 $SIGMA_MICRO
\ No newline at end of file +nickle kalman_micro.5c -p AO_MK_BARO -c baro -t 0.096 $SIGMA_MICRO +nickle kalman_micro.5c -p AO_MK2_BARO -c baro -t 0.1 $SIGMA_MICRO diff --git a/telegps/Makefile.am b/telegps/Makefile.am index 3484b951..bd69bd50 100644 --- a/telegps/Makefile.am +++ b/telegps/Makefile.am @@ -108,7 +108,8 @@ FIRMWARE_TD=$(FIRMWARE_TD_0_2) $(FIRMWARE_TD_3_0)  FIRMWARE_TBT_1_0=$(top_srcdir)/src/telebt-v1.0/telebt-v1.0-$(VERSION).ihx  FIRMWARE_TBT_3_0=$(top_srcdir)/src/telebt-v3.0/telebt-v3.0-$(VERSION).ihx -FIRMWARE_TBT=$(FIRMWARE_TBT_1_0) $(FIRMWARE_TBT_3_0) +FIRMWARE_TBT_4_0=$(top_srcdir)/src/telebt-v4.0/telebt-v4.0-$(VERSION).ihx +FIRMWARE_TBT=$(FIRMWARE_TBT_1_0) $(FIRMWARE_TBT_3_0) $(FIRMWARE_TBT_4_0)  FIRMWARE_TG_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx  FIRMWARE_TG=$(FIRMWARE_TG_1_0) diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index 66eaaa2b..3646f000 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -25,8 +25,8 @@ import java.io.*;  import java.util.concurrent.*;  import java.util.*;  import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class TeleGPS  	extends AltosUIFrame @@ -152,7 +152,7 @@ public class TeleGPS  			status_update.saved_listener_state = listener_state;  			if (state == null) -				state = new AltosState(); +				state = new AltosState(new AltosCalData());  			int i = 0;  			for (AltosFlightDisplay display : displays) { @@ -287,23 +287,30 @@ public class TeleGPS  		new TeleGPSConfig(this);  	} +	private static AltosFlightSeries make_series(AltosRecordSet set) { +		AltosFlightSeries series = new AltosFlightSeries(set.cal_data()); +		set.capture_series(series); +		series.finish(); +		return series; +	} +  	void export() { -		AltosDataChooser chooser; -		chooser = new AltosDataChooser(this); -		AltosStateIterable states = chooser.runDialog(); -		if (states == null) +		AltosDataChooser chooser = new AltosDataChooser(this); + +		AltosRecordSet set = chooser.runDialog(); +		if (set == null)  			return; -		new AltosCSVUI(this, states, chooser.file()); +		AltosFlightSeries series = make_series(set); +		new AltosCSVUI(this, series, chooser.file());  	}  	void graph() { -		AltosDataChooser chooser; -		chooser = new AltosDataChooser(this); -		AltosStateIterable states = chooser.runDialog(); -		if (states == null) +		AltosDataChooser chooser = new AltosDataChooser(this); +		AltosRecordSet set = chooser.runDialog(); +		if (set == null)  			return;  		try { -			new TeleGPSGraphUI(states, chooser.file()); +			new TeleGPSGraphUI(set, chooser.file());  		} catch (InterruptedException ie) {  		} catch (IOException ie) {  		} @@ -612,33 +619,28 @@ public class TeleGPS  		connect(device);  	} -	static AltosStateIterable record_iterable(File file) { -		FileInputStream in; +	static AltosRecordSet record_set(File file) {  		try { -			in = new FileInputStream(file); -		} catch (Exception e) { -			System.out.printf("Failed to open file '%s'\n", file); -			return null; -		} -		if (file.getName().endsWith("telem")) -			return new AltosTelemetryFile(in); -		else -			return new AltosEepromFile(in); +			return AltosLib.record_set(file); +		} catch (IOException ie) { +			System.out.printf("%s\n", ie.getMessage()); +                } +                return null;  	}  	static AltosReplayReader replay_file(File file) { -		AltosStateIterable states = record_iterable(file); -		if (states == null) +		AltosRecordSet set = record_set(file); +		if (set == null)  			return null; -		return new AltosReplayReader(states.iterator(), file); +		return new AltosReplayReader(set, file);  	}  	static boolean process_graph(File file) { -		AltosStateIterable states = record_iterable(file); -		if (states == null) +		AltosRecordSet set = record_set(file); +		if (set == null)  			return false;  		try { -			new TeleGPSGraphUI(states, file); +			new TeleGPSGraphUI(set, file);  		} catch (Exception e) {  			return false;  		} diff --git a/telegps/TeleGPSConfig.java b/telegps/TeleGPSConfig.java index d24e7471..7fc15ba9 100644 --- a/telegps/TeleGPSConfig.java +++ b/telegps/TeleGPSConfig.java @@ -23,8 +23,8 @@ import javax.swing.*;  import java.io.*;  import java.util.concurrent.*;  import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class TeleGPSConfig implements ActionListener { diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java index dd3965b4..88ced192 100644 --- a/telegps/TeleGPSConfigUI.java +++ b/telegps/TeleGPSConfigUI.java @@ -23,8 +23,8 @@ import java.awt.*;  import java.awt.event.*;  import javax.swing.*;  import javax.swing.event.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class TeleGPSConfigUI  	extends AltosUIDialog @@ -131,7 +131,7 @@ public class TeleGPSConfigUI  	}  	public double pyro_firing_time() { -		return -1; +		return AltosLib.MISSING;  	}  	boolean is_telemetrum() { @@ -140,46 +140,46 @@ public class TeleGPSConfigUI  	}  	void set_radio_enable_tool_tip() { -		if (radio_enable_value.isEnabled()) +		if (radio_enable_value.isVisible())  			radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");  		else  			radio_enable_value.setToolTipText("Firmware version does not support disabling radio");  	}  	void set_rate_tool_tip() { -		if (rate_value.isEnabled()) +		if (rate_value.isVisible())  			rate_value.setToolTipText("Select telemetry baud rate");  		else  			rate_value.setToolTipText("Firmware version does not support variable telemetry rates");  	}  	void set_aprs_interval_tool_tip() { -		if (aprs_interval_value.isEnabled()) +		if (aprs_interval_value.isVisible())  			aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports");  		else  			aprs_interval_value.setToolTipText("Hardware doesn't support APRS");  	}  	void set_aprs_ssid_tool_tip() { -		if (aprs_ssid_value.isEnabled()) +		if (aprs_ssid_value.isVisible())  			aprs_ssid_value.setToolTipText("Set the APRS SSID (secondary station identifier)"); -		else if (aprs_ssid_value.isEnabled()) +		else if (aprs_ssid_value.isVisible())  			aprs_ssid_value.setToolTipText("Software version doesn't support setting the APRS SSID");  		else  			aprs_ssid_value.setToolTipText("Hardware doesn't support APRS");  	}  	void set_aprs_format_tool_tip() { -		if (aprs_format_value.isEnabled()) +		if (aprs_format_value.isVisible())  			aprs_format_value.setToolTipText("Set the APRS format (compressed/uncompressed)"); -		else if (aprs_format_value.isEnabled()) +		else if (aprs_format_value.isVisible())  			aprs_format_value.setToolTipText("Software version doesn't support setting the APRS format");  		else  			aprs_format_value.setToolTipText("Hardware doesn't support APRS");  	}  	void set_flight_log_max_tool_tip() { -		if (flight_log_max_value.isEnabled()) +		if (flight_log_max_value.isVisible())  			flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");  		else  			flight_log_max_value.setToolTipText("Cannot set max value with flight logs in memory"); @@ -675,7 +675,7 @@ public class TeleGPSConfigUI  	public void units_changed(boolean imperial_units) {  		boolean	was_dirty = dirty; -		if (tracker_motion_value.isEnabled()) { +		if (tracker_motion_value.isVisible()) {  			String motion = tracker_motion_value.getSelectedItem().toString();  			tracker_motion_label.setText(get_tracker_motion_label());  			set_tracker_motion_values(); @@ -712,21 +712,24 @@ public class TeleGPSConfigUI  	}  	public int main_deploy() { -		return -1; +		return AltosLib.MISSING;  	}  	public void set_apogee_delay(int new_apogee_delay) { }  	public int apogee_delay() { -		return -1; +		return AltosLib.MISSING;  	}  	public void set_apogee_lockout(int new_apogee_lockout) { } -	public int apogee_lockout() { return -1; } +	public int apogee_lockout() { return AltosLib.MISSING; }  	public void set_radio_frequency(double new_radio_frequency) { -		radio_frequency_value.set_frequency(new_radio_frequency); +		if (new_radio_frequency != AltosLib.MISSING) +			radio_frequency_value.set_frequency(new_radio_frequency); +		radio_frequency_label.setVisible(new_radio_frequency != AltosLib.MISSING); +		radio_frequency_value.setVisible(new_radio_frequency != AltosLib.MISSING);  	}  	public double radio_frequency() { @@ -734,45 +737,32 @@ public class TeleGPSConfigUI  	}  	public void set_radio_calibration(int new_radio_calibration) { -		radio_calibration_value.setVisible(new_radio_calibration >= 0); -		if (new_radio_calibration < 0) -			radio_calibration_value.setText("Disabled"); -		else +		if (new_radio_calibration != AltosLib.MISSING)  			radio_calibration_value.setText(String.format("%d", new_radio_calibration)); -	} - -	private int parse_int(String name, String s, boolean split) throws AltosConfigDataException { -		String v = s; -		if (split) -			v = s.split("\\s+")[0]; -		try { -			return Integer.parseInt(v); -		} catch (NumberFormatException ne) { -			throw new AltosConfigDataException("Invalid %s \"%s\"", name, s); -		} +		radio_calibration_value.setVisible(new_radio_calibration == AltosLib.MISSING); +		radio_calibration_label.setVisible(new_radio_calibration == AltosLib.MISSING);  	}  	public void set_radio_enable(int new_radio_enable) { -		if (new_radio_enable >= 0) { -			radio_enable_value.setSelected(new_radio_enable > 0); -			radio_enable_value.setEnabled(true); -		} else { -			radio_enable_value.setSelected(true); -			radio_enable_value.setVisible(radio_frequency() > 0); -			radio_enable_value.setEnabled(false); -		} +		if (new_radio_enable != AltosLib.MISSING) +			radio_enable_value.setSelected(new_radio_enable != 0); +		radio_enable_label.setVisible(new_radio_enable != AltosLib.MISSING); +		radio_enable_value.setVisible(new_radio_enable != AltosLib.MISSING);  		set_radio_enable_tool_tip();  	}  	public int radio_enable() { -		if (radio_enable_value.isEnabled()) +		if (radio_enable_value.isVisible())  			return radio_enable_value.isSelected() ? 1 : 0;  		else -			return -1; +			return AltosLib.MISSING;  	}  	public void set_telemetry_rate(int new_rate) { -		rate_value.set_rate(new_rate); +		if (new_rate != AltosLib.MISSING) +			rate_value.set_rate(new_rate); +		rate_label.setVisible(new_rate != AltosLib.MISSING); +		rate_value.setVisible(new_rate != AltosLib.MISSING);  	}  	public int telemetry_rate() { @@ -780,12 +770,27 @@ public class TeleGPSConfigUI  	}  	public void set_callsign(String new_callsign) { +		if (new_callsign != null) +			callsign_value.setText(new_callsign);  		callsign_value.setVisible(new_callsign != null); -		callsign_value.setText(new_callsign); +		callsign_label.setVisible(new_callsign != null);  	}  	public String callsign() { -		return callsign_value.getText(); +		if (callsign_value.isVisible()) +			return callsign_value.getText(); +		return null; +	} + +	private int parse_int(String name, String s, boolean split) throws AltosConfigDataException { +		String v = s; +		if (split) +			v = s.split("\\s+")[0]; +		try { +			return Integer.parseInt(v); +		} catch (NumberFormatException ne) { +			throw new AltosConfigDataException("Invalid %s \"%s\"", name, s); +		}  	}  	int	flight_log_max_limit; @@ -828,15 +833,15 @@ public class TeleGPSConfigUI  	}  	public void set_ignite_mode(int new_ignite_mode) { } -	public int ignite_mode() { return -1; } +	public int ignite_mode() { return AltosLib.MISSING; }  	public void set_pad_orientation(int new_pad_orientation) { } -	public int pad_orientation() { return -1; } +	public int pad_orientation() { return AltosLib.MISSING; }  	public void set_beep(int new_beep) { } -	public int beep() { return -1; } +	public int beep() { return AltosLib.MISSING; }  	String[] tracker_motion_values() {  		if (AltosConvert.imperial_units) @@ -859,87 +864,92 @@ public class TeleGPSConfigUI  	}  	void set_tracker_tool_tip() { -		if (tracker_motion_value.isEnabled()) +		if (tracker_motion_value.isVisible())  			tracker_motion_value.setToolTipText("How far the device must move before logging");  		else  			tracker_motion_value.setToolTipText("This device doesn't disable logging when stationary"); -		if (tracker_interval_value.isEnabled()) +		if (tracker_interval_value.isVisible())  			tracker_interval_value.setToolTipText("How often to report GPS position");  		else  			tracker_interval_value.setToolTipText("This device can't configure interval");  	}  	public void set_tracker_motion(int tracker_motion) { -		if (tracker_motion < 0) { -			tracker_motion_value.setEnabled(false); -		} else { -			tracker_motion_value.setEnabled(true); +		if (tracker_motion != AltosLib.MISSING)  			tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion)); -		} +		tracker_motion_label.setVisible(tracker_motion != AltosLib.MISSING); +		tracker_motion_value.setVisible(tracker_motion != AltosLib.MISSING);  	}  	public int tracker_motion() throws AltosConfigDataException { -		String str = tracker_motion_value.getSelectedItem().toString(); -		try { -			return (int) (AltosConvert.height.parse_locale(str) + 0.5); -		} catch (ParseException pe) { -			throw new AltosConfigDataException("invalid tracker motion %s", str); +		if (tracker_motion_value.isVisible()) { +			String str = tracker_motion_value.getSelectedItem().toString(); +			try { +				return (int) (AltosConvert.height.parse_locale(str) + 0.5); +			} catch (ParseException pe) { +				throw new AltosConfigDataException("invalid tracker motion %s", str); +			}  		} +		return AltosLib.MISSING;  	}  	public void set_tracker_interval(int tracker_interval) { -		if (tracker_interval< 0) { -			tracker_interval_value.setEnabled(false); -		} else { -			tracker_interval_value.setEnabled(true); +		if (tracker_interval != AltosLib.MISSING)  			tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval)); -		} +		tracker_interval_label.setVisible(tracker_interval != AltosLib.MISSING); +		tracker_interval_value.setVisible(tracker_interval != AltosLib.MISSING);  	}  	public int tracker_interval() throws AltosConfigDataException { -		return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false); +		if (tracker_interval_value.isVisible()) +			return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false); +		return AltosLib.MISSING;  	}  	public void set_aprs_interval(int new_aprs_interval) { -		String	s; - -		if (new_aprs_interval <= 0) -			s = "Disabled"; -		else -			s = Integer.toString(new_aprs_interval); -		aprs_interval_value.setSelectedItem(s); -		aprs_interval_value.setVisible(new_aprs_interval >= 0); +		if (new_aprs_interval != AltosLib.MISSING) +			aprs_interval_value.setSelectedItem(Integer.toString(new_aprs_interval)); +		aprs_interval_value.setVisible(new_aprs_interval != AltosLib.MISSING); +		aprs_interval_label.setVisible(new_aprs_interval != AltosLib.MISSING);  		set_aprs_interval_tool_tip();  	}  	public int aprs_interval() throws AltosConfigDataException { -		String	s = aprs_interval_value.getSelectedItem().toString(); +		if (aprs_interval_value.isVisible()) { +			String	s = aprs_interval_value.getSelectedItem().toString(); -		if (s.equals("Disabled")) -			return 0; -		return parse_int("aprs interval", s, false); +			return parse_int("aprs interval", s, false); +		} +		return AltosLib.MISSING;  	}  	public void set_aprs_ssid(int new_aprs_ssid) { -		aprs_ssid_value.setSelectedItem(Math.max(0,new_aprs_ssid)); -		aprs_ssid_value.setVisible(new_aprs_ssid >= 0); +		if (new_aprs_ssid != AltosLib.MISSING) +			aprs_ssid_value.setSelectedItem(new_aprs_ssid); +		aprs_ssid_value.setVisible(new_aprs_ssid != AltosLib.MISSING); +		aprs_ssid_label.setVisible(new_aprs_ssid != AltosLib.MISSING);  		set_aprs_ssid_tool_tip();  	}  	public int aprs_ssid() throws AltosConfigDataException { -		Integer i = (Integer) aprs_ssid_value.getSelectedItem(); -		return i; +		if (aprs_ssid_value.isVisible()) { +			Integer i = (Integer) aprs_ssid_value.getSelectedItem(); +			return i; +		} +		return AltosLib.MISSING;  	}  	public void set_aprs_format(int new_aprs_format) { -		aprs_format_value.setVisible(new_aprs_format >= 0); -		aprs_format_label.setVisible(new_aprs_format >= 0); - -		aprs_format_value.setSelectedIndex(Math.max(0,new_aprs_format)); +		if (new_aprs_format != AltosLib.MISSING) +			aprs_format_value.setSelectedIndex(new_aprs_format); +		aprs_format_value.setVisible(new_aprs_format != AltosLib.MISSING); +		aprs_format_label.setVisible(new_aprs_format != AltosLib.MISSING);  		set_aprs_format_tool_tip();  	}  	public int aprs_format() throws AltosConfigDataException { -		return aprs_format_value.getSelectedIndex(); +		if (aprs_format_value.isVisible()) +			return aprs_format_value.getSelectedIndex(); +		return AltosLib.MISSING;  	}  } diff --git a/telegps/TeleGPSDisplayThread.java b/telegps/TeleGPSDisplayThread.java index a9c80dc0..fdf0e201 100644 --- a/telegps/TeleGPSDisplayThread.java +++ b/telegps/TeleGPSDisplayThread.java @@ -22,8 +22,8 @@ import java.awt.*;  import javax.swing.*;  import java.io.*;  import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class TeleGPSDisplayThread extends Thread { @@ -31,7 +31,9 @@ public class TeleGPSDisplayThread extends Thread {  	IdleThread		idle_thread;  	AltosVoice		voice;  	AltosFlightReader	reader; -	AltosState		old_state, state; +	AltosState		state; +	int			old_state = AltosLib.ao_flight_invalid; +	boolean			old_gps_ready = false;  	AltosListenerState	listener_state;  	AltosFlightDisplay	display; @@ -130,11 +132,12 @@ public class TeleGPSDisplayThread extends Thread {  		}  		public synchronized void notice(boolean spoken) { -			if (old_state != null && old_state.state() != state.state()) { +			if (old_state != state.state()) {  				report_time = now();  				this.notify();  			} else if (spoken)  				set_report_time(); +			old_state = state.state();  		}  		public IdleThread() { @@ -144,17 +147,17 @@ public class TeleGPSDisplayThread extends Thread {  	synchronized boolean tell() {  		boolean	ret = false; -		if (old_state == null || old_state.gps_ready != state.gps_ready) { +		if (old_gps_ready != state.gps_ready) {  			if (state.gps_ready) {  				voice.speak("GPS ready");  				ret = true;  			} -			else if (old_state != null) { +			else if (old_gps_ready) {  				voice.speak("GPS lost");  				ret = true;  			} +			old_gps_ready = state.gps_ready;  		} -		old_state = state;  		return ret;  	} @@ -173,7 +176,6 @@ public class TeleGPSDisplayThread extends Thread {  						listener_state.running = false;  						break;  					} -					reader.update(state);  					show_safely();  					told = tell();  					idle_thread.notice(told); diff --git a/telegps/TeleGPSGraphUI.java b/telegps/TeleGPSGraphUI.java index 55ee370e..9d8c6bf5 100644 --- a/telegps/TeleGPSGraphUI.java +++ b/telegps/TeleGPSGraphUI.java @@ -27,14 +27,14 @@ import javax.swing.*;  import java.io.*;  import java.util.concurrent.*;  import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  import org.jfree.chart.ChartPanel;  import org.jfree.chart.JFreeChart;  import org.jfree.ui.RefineryUtilities; -public class TeleGPSGraphUI extends AltosUIFrame +public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener  {  	JTabbedPane		pane;  	AltosGraph		graph; @@ -42,13 +42,33 @@ public class TeleGPSGraphUI extends AltosUIFrame  	AltosUIMap		map;  	AltosState		state;  	AltosFlightStats	stats; -	AltosGraphDataSet	graphDataSet;  	AltosFlightStatsTable	statsTable; - -	void fill_map(AltosStateIterable states) { -		for (AltosState state : states) { -			if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) -				map.show(state, null); +	AltosGPS		gps; +	boolean			has_gps; + +	void fill_map(AltosFlightSeries flight_series) { +		boolean			any_gps = false; +		AltosGPSTimeValue	gtv_last = null; + +		if (flight_series.gps_series != null) { +			for (AltosGPSTimeValue gtv : flight_series.gps_series) { +				gtv_last = gtv; +				AltosGPS gps = gtv.gps; +				if (gps != null && +				    gps.locked && +				    gps.nsat >= 4) { +					if (map == null) +						map = new AltosUIMap(); +					map.show(gps, (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time)); +					this.gps = gps; +					has_gps = true; +				} +			} +		} +		if (gtv_last != null) { +			int state = (int) flight_series.value_after(AltosFlightSeries.state_name, gtv_last.time); +			if (state == AltosLib.ao_flight_landed) +				map.show(gtv_last.gps, state);  		}  	} @@ -58,16 +78,35 @@ public class TeleGPSGraphUI extends AltosUIFrame  		TeleGPS.subtract_window();  	} -	TeleGPSGraphUI(AltosStateIterable states, File file) throws InterruptedException, IOException { +	public void font_size_changed(int font_size) { +		if (map != null) +			map.font_size_changed(font_size); +		if (statsTable != null) +			statsTable.font_size_changed(font_size); +	} + +	public void units_changed(boolean imperial_units) { +		if (map != null) +			map.units_changed(imperial_units); +		if (enable != null) +			enable.units_changed(imperial_units); +	} + +	TeleGPSGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException {  		super(file.getName()); -		state = null; +		AltosCalData cal_data = set.cal_data(); + +		AltosUIFlightSeries flight_series = new AltosUIFlightSeries(cal_data); +		set.capture_series(flight_series); +		flight_series.finish();  		pane = new JTabbedPane();  		enable = new AltosUIEnable(); -		stats = new AltosFlightStats(states); -		graphDataSet = new AltosGraphDataSet(states); -		graph = new AltosGraph(enable, stats, graphDataSet); +		stats = new AltosFlightStats(flight_series); + +		graph = new AltosGraph(enable, stats, flight_series); +  		statsTable = new AltosFlightStatsTable(stats);  		map = new AltosUIMap(); @@ -75,11 +114,14 @@ public class TeleGPSGraphUI extends AltosUIFrame  		pane.add("Graph", graph.panel);  		pane.add("Configure Graph", enable);  		pane.add("Statistics", statsTable); -		fill_map(states); +		fill_map(flight_series);  		pane.add("Map", map);  		setContentPane (pane); +		AltosUIPreferences.register_font_listener(this); +		AltosPreferences.register_units_listener(this); +  		addWindowListener(new WindowAdapter() {  				@Override  				public void windowClosing(WindowEvent e) { diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java index f4fa7216..383a0a44 100644 --- a/telegps/TeleGPSInfo.java +++ b/telegps/TeleGPSInfo.java @@ -22,8 +22,8 @@ import java.util.*;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class TeleGPSInfo extends AltosUIFlightTab { diff --git a/telegps/TeleGPSPreferences.java b/telegps/TeleGPSPreferences.java index 61952326..58b3ae35 100644 --- a/telegps/TeleGPSPreferences.java +++ b/telegps/TeleGPSPreferences.java @@ -23,7 +23,7 @@ import java.awt.event.*;  import java.beans.*;  import javax.swing.*;  import javax.swing.event.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*;  public class TeleGPSPreferences  	extends AltosUIConfigure diff --git a/telegps/TeleGPSState.java b/telegps/TeleGPSState.java index 9ba0b7a5..21173394 100644 --- a/telegps/TeleGPSState.java +++ b/telegps/TeleGPSState.java @@ -22,8 +22,8 @@ import java.util.*;  import java.awt.*;  import java.awt.event.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class TeleGPSState extends AltosUIFlightTab { @@ -124,10 +124,11 @@ public class TeleGPSState extends AltosUIFlightTab {  	class FirmwareVersion extends AltosUIIndicator {  		public void show(AltosState state, AltosListenerState listener_state) { -			if (state.firmware_version == null) +			AltosCalData cal_data = state.cal_data(); +			if (cal_data.firmware_version == null)  				show("Missing");  			else -				show(state.firmware_version); +				show(cal_data.firmware_version);  		}  		public FirmwareVersion(Container container, int y) { @@ -137,9 +138,8 @@ public class TeleGPSState extends AltosUIFlightTab {  	class FlightLogMax extends AltosUIIndicator {  		public void show(AltosState state, AltosListenerState listener_state) { -			int storage = state.flight_log_max; -			if (storage == AltosLib.MISSING) -				storage = state.log_space >> 10; +			AltosCalData cal_data = state.cal_data(); +			int storage = cal_data.flight_log_max;  			if (storage == AltosLib.MISSING)  				show("Missing");  			else diff --git a/telegps/TeleGPSStatus.java b/telegps/TeleGPSStatus.java index 5479f43a..e1be69a4 100644 --- a/telegps/TeleGPSStatus.java +++ b/telegps/TeleGPSStatus.java @@ -20,8 +20,8 @@ package org.altusmetrum.telegps;  import java.awt.*;  import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*;  public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {  	GridBagLayout	layout; @@ -75,11 +75,14 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {  		String	call;  		void show(AltosState state, AltosListenerState listener_state) { -			if (state.callsign != call) { -				value.setText(state.callsign); -				call = state.callsign; +			AltosCalData cal_data = state.cal_data(); +			if (cal_data == null) +				System.out.printf("null cal data?\n"); +			if (cal_data.callsign != call) { +				value.setText(cal_data.callsign); +				call = cal_data.callsign;  			} -			if (state.callsign == null) +			if (cal_data.callsign == null)  				setVisible(false);  			else  				setVisible(true); @@ -100,12 +103,13 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {  	class Serial extends Value {  		int	serial = -1;  		void show(AltosState state, AltosListenerState listener_state) { -			if (state.serial != serial) { -				if (state.serial == AltosLib.MISSING) +			AltosCalData cal_data = state.cal_data(); +			if (cal_data.serial != serial) { +				if (cal_data.serial == AltosLib.MISSING)  					value.setText("none");  				else -					value.setText(String.format("%d", state.serial)); -				serial = state.serial; +					value.setText(String.format("%d", cal_data.serial)); +				serial = cal_data.serial;  			}  		} @@ -126,12 +130,13 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {  		int	last_flight = -1;  		void show(AltosState state, AltosListenerState listener_state) { -			if (state.flight != last_flight) { -				if (state.flight == AltosLib.MISSING) +			AltosCalData cal_data = state.cal_data(); +			if (cal_data.flight != last_flight) { +				if (cal_data.flight == AltosLib.MISSING)  					value.setText("none");  				else -					value.setText(String.format("%d", state.flight)); -				last_flight = state.flight; +					value.setText(String.format("%d", cal_data.flight)); +				last_flight = cal_data.flight;  			}  		} diff --git a/telegps/TeleGPSStatusUpdate.java b/telegps/TeleGPSStatusUpdate.java index ac37af31..1b66d142 100644 --- a/telegps/TeleGPSStatusUpdate.java +++ b/telegps/TeleGPSStatusUpdate.java @@ -19,7 +19,7 @@  package org.altusmetrum.telegps;  import java.awt.event.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*;  public class TeleGPSStatusUpdate implements ActionListener { diff --git a/telegps/telegps-windows.nsi.in b/telegps/telegps-windows.nsi.in index b0b5d6a6..d0cd969c 100644 --- a/telegps/telegps-windows.nsi.in +++ b/telegps/telegps-windows.nsi.in @@ -124,6 +124,8 @@ Section "TeleGPS, TeleDongle and TeleBT Firmware"  	File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"  	File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"  	File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx" +	File "../src/telebt-v3.0/telebt-v3.0-${VERSION}.ihx" +	File "../src/telebt-v4.0/telebt-v4.0-${VERSION}.ihx"  SectionEnd  | 
