From 1f4c46ccc8edb56170a7b3055de3fd1310bb93c9 Mon Sep 17 00:00:00 2001 From: Nicholas Sherlock Date: Sun, 27 Nov 2016 17:39:42 +1300 Subject: [PATCH] Support logs longer than 71.6 minutes (track 32-bit time field rollover) --- js/flightlog.js | 2 + js/flightlog_index.js | 7 +-- js/flightlog_parser.js | 117 +++++++++++++++++++++++++---------------- 3 files changed, 77 insertions(+), 49 deletions(-) diff --git a/js/flightlog.js b/js/flightlog.js index 03352a0..0ec8c36 100644 --- a/js/flightlog.js +++ b/js/flightlog.js @@ -401,6 +401,8 @@ function FlightLog(logData) { parser.resetDataState(); //Prime the parser with the previous state we get from the flightlog index, so it can base deltas off that data + parser.setTimeRolloverAccumulator(iframeDirectory.initialTimeRolloverAccumulator[chunkIndex]); + if (iframeDirectory.initialGPSHome) { parser.setGPSHomeHistory(iframeDirectory.initialGPSHome[chunkIndex]); } diff --git a/js/flightlog_index.js b/js/flightlog_index.js index f514460..d0db2e8 100644 --- a/js/flightlog_index.js +++ b/js/flightlog_index.js @@ -5,7 +5,6 @@ function FlightLogIndex(logData) { var that = this, logBeginOffsets = false, - logCount = false, intraframeDirectories = false; function buildLogOffsetsIndex() { @@ -46,19 +45,17 @@ function FlightLogIndex(logData) { initialIMU: [], initialSlow: [], initialGPSHome: [], + initialTimeRolloverAccumulator: [], hasEvent: [], minTime: false, maxTime: false }, imu = new IMU(), - gyroADC, accSmooth, magADC, iframeCount = 0, motorFields = [], - matches, throttleTotal, - eventInThisChunk = null, parsedHeader, sawEndMarker = false; @@ -122,6 +119,7 @@ function FlightLogIndex(logData) { // Log the beginning of the new chunk intraIndex.times.push(frameTime); intraIndex.offsets.push(frameOffset); + intraIndex.initialTimeRolloverAccumulator.push(frameTime - (frameTime >>> 0) /* i.e. frameTime with the lower 32-bits masked out */); if (motorFields.length) { throttleTotal = 0; @@ -218,7 +216,6 @@ function FlightLogIndex(logData) { var lastTime, lastLastTime, lastOffset, lastLastOffset, - lastThrottle, sourceIndex = intraframeDirectories[i], diff --git a/js/flightlog_parser.js b/js/flightlog_parser.js index 26b6fe7..3579a9c 100644 --- a/js/flightlog_parser.js +++ b/js/flightlog_parser.js @@ -217,6 +217,9 @@ var FlightLogParser = function(logData) { // Details about the last main frame that was successfully parsed lastMainFrameIteration, lastMainFrameTime, + + // When 32-bit time values roll over to zero, we add 2^32 to this accumulator so it can be added to the time: + timeRolloverAccumulator = 0, //The actual log data stream we're reading: stream; @@ -453,51 +456,74 @@ var FlightLogParser = function(logData) { } } } + + function castTo32BitUnsigned(val) { + return val >>> 0; + } + + function applyTimeRollover() { + if (lastMainFrameTime != -1) { + if ( + // If we appeared to travel backwards in time (modulo 32 bits)... + (castTo32BitUnsigned(mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME]) < castTo32BitUnsigned(lastMainFrameTime)) + // But we actually just incremented a reasonable amount (modulo 32-bits)... + && castTo32BitUnsigned(castTo32BitUnsigned(mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME]) - castTo32BitUnsigned(lastMainFrameTime)) < MAXIMUM_TIME_JUMP_BETWEEN_FRAMES + ) { + // 32-bit time counter has wrapped, so add 2^32 to the timestamp + timeRolloverAccumulator += 0x100000000; + } + } + + mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME] = castTo32BitUnsigned(mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME]) + timeRolloverAccumulator; + } + + function validateMainFrameValues() { + // Check that iteration count and time didn't move backwards, and didn't move forward too much. + return ( + mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_ITERATION] >= lastMainFrameIteration + && mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_ITERATION] < lastMainFrameIteration + MAXIMUM_ITERATION_JUMP_BETWEEN_FRAMES + && mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME] >= lastMainFrameTime + && mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME] < lastMainFrameTime + MAXIMUM_TIME_JUMP_BETWEEN_FRAMES + ); + } function completeIntraframe(frameType, frameStart, frameEnd, raw) { - var acceptFrame = true; + applyTimeRollover(); + + // Only attempt to validate the frame values if we have something to check it against + if (!raw && lastMainFrameIteration != -1 && !validateMainFrameValues()) { + invalidateMainStream(); + } else { + mainStreamIsValid = true; + } - // Do we have a previous frame to use as a reference to validate field values against? - if (!raw && lastMainFrameIteration != -1) { - /* - * Check that iteration count and time didn't move backwards, and didn't move forward too much. - */ - acceptFrame = - mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_ITERATION] >= lastMainFrameIteration - && mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_ITERATION] < lastMainFrameIteration + MAXIMUM_ITERATION_JUMP_BETWEEN_FRAMES - && mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME] >= lastMainFrameTime - && mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME] < lastMainFrameTime + MAXIMUM_TIME_JUMP_BETWEEN_FRAMES; - } - - if (acceptFrame) { + if (mainStreamIsValid) { that.stats.intentionallyAbsentIterations += countIntentionallySkippedFramesTo(mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_ITERATION]); lastMainFrameIteration = mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_ITERATION]; lastMainFrameTime = mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME]; - - mainStreamIsValid = true; - + updateFieldStatistics(frameType, mainHistory[0]); - } else { - invalidateMainStream(); } if (that.onFrameReady) that.onFrameReady(mainStreamIsValid, mainHistory[0], frameType, frameStart, frameEnd - frameStart); - // Rotate history buffers - - // Both the previous and previous-previous states become the I-frame, because we can't look further into the past than the I-frame - mainHistory[1] = mainHistory[0]; - mainHistory[2] = mainHistory[0]; - - // And advance the current frame into an empty space ready to be filled - if (mainHistory[0] == mainHistoryRing[0]) - mainHistory[0] = mainHistoryRing[1]; - else if (mainHistory[0] == mainHistoryRing[1]) - mainHistory[0] = mainHistoryRing[2]; - else - mainHistory[0] = mainHistoryRing[0]; + if (mainStreamIsValid) { + // Rotate history buffers + + // Both the previous and previous-previous states become the I-frame, because we can't look further into the past than the I-frame + mainHistory[1] = mainHistory[0]; + mainHistory[2] = mainHistory[0]; + + // And advance the current frame into an empty space ready to be filled + if (mainHistory[0] == mainHistoryRing[0]) + mainHistory[0] = mainHistoryRing[1]; + else if (mainHistory[0] == mainHistoryRing[1]) + mainHistory[0] = mainHistoryRing[2]; + else + mainHistory[0] = mainHistoryRing[0]; + } } /** @@ -642,16 +668,13 @@ var FlightLogParser = function(logData) { } function completeInterframe(frameType, frameStart, frameEnd, raw) { - // Reject this frame if the time or iteration count jumped too far - if (mainStreamIsValid && !raw - && ( - mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME] > lastMainFrameTime + MAXIMUM_TIME_JUMP_BETWEEN_FRAMES - || mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_ITERATION] > lastMainFrameIteration + MAXIMUM_ITERATION_JUMP_BETWEEN_FRAMES - )) { - mainStreamIsValid = false; - } - - if (mainStreamIsValid) { + applyTimeRollover(); + + if (mainStreamIsValid && !raw && !validateMainFrameValues()) { + invalidateMainStream(); + } + + if (mainStreamIsValid) { lastMainFrameIteration = mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_ITERATION]; lastMainFrameTime = mainHistory[0][FlightLogParser.prototype.FLIGHT_LOG_FIELD_INDEX_TIME]; @@ -865,7 +888,7 @@ var FlightLogParser = function(logData) { switch (eventType) { case FlightLogEvent.SYNC_BEEP: - lastEvent.data.time = stream.readUnsignedVB(); + lastEvent.data.time = stream.readUnsignedVB() + timeRolloverAccumulator; lastEvent.time = lastEvent.data.time; break; case FlightLogEvent.AUTOTUNE_CYCLE_START: @@ -921,7 +944,7 @@ var FlightLogParser = function(logData) { break; case FlightLogEvent.LOGGING_RESUME: lastEvent.data.logIteration = stream.readUnsignedVB(); - lastEvent.data.currentTime = stream.readUnsignedVB(); + lastEvent.data.currentTime = stream.readUnsignedVB() + timeRolloverAccumulator; break; case FlightLogEvent.LOG_END: var endMessage = stream.readString(END_OF_LOG_MESSAGE.length); @@ -952,6 +975,8 @@ var FlightLogParser = function(logData) { lastMainFrameIteration = -1; lastMainFrameTime = -1; + + timeRolloverAccumulator = 0; invalidateMainStream(); gpsHomeIsValid = false; @@ -1073,6 +1098,9 @@ var FlightLogParser = function(logData) { } }; + this.setTimeRolloverAccumulator = function(newTimeRolloverAccumulator) { + timeRolloverAccumulator = newTimeRolloverAccumulator; + }; /** * Continue the current parse by scanning the given range of offsets for data. To begin an independent parse, @@ -1111,6 +1139,7 @@ var FlightLogParser = function(logData) { sizeCount: new Int32Array(256), /* int32 arrays are zero-filled, handy! */ validCount: 0, corruptCount: 0, + desyncCount: 0, field: [] }; }