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 |