Update to the 2019 wpilib
Lots of gratuitious incompatibilities to deal with. Started sanifying a
few classes rather than figuring out how to update them too. Has not yet
been tested on a robot, but everything still builds so it should be
fine.
Also ported over our FPGA timestamp fixes, which were previously only in
allwpilib_2018.
Also upgraded to the new roborio compiler, which has to happen at the
same time due to incompatible pre-compiled libraries.
Change-Id: Ib9b6ad8fc0112d90a9855afe1b706588ef4ebde9
diff --git a/frc971/wpilib/ahal/InterruptableSensorBase.cc b/frc971/wpilib/ahal/InterruptableSensorBase.cc
index a757bee..4becafc 100644
--- a/frc971/wpilib/ahal/InterruptableSensorBase.cc
+++ b/frc971/wpilib/ahal/InterruptableSensorBase.cc
@@ -7,47 +7,50 @@
#include "frc971/wpilib/ahal/InterruptableSensorBase.h"
-#include "HAL/HAL.h"
+#include "hal/HAL.h"
#include "frc971/wpilib/ahal/Utility.h"
#include "frc971/wpilib/ahal/WPIErrors.h"
using namespace frc;
-InterruptableSensorBase::InterruptableSensorBase() {}
+namespace {
-/**
- * Request one of the 8 interrupts asynchronously on this digital input.
- *
- * Request interrupts in asynchronous mode where the user's interrupt handler
- * will be called when the interrupt fires. Users that want control over the
- * thread priority should use the synchronous method with their own spawned
- * thread. The default is interrupt on rising edges only.
- */
-void InterruptableSensorBase::RequestInterrupts(
- HAL_InterruptHandlerFunction handler, void *param) {
- if (StatusIsFatal()) return;
+// Converts a freestanding lower half to a 64 bit FPGA timestamp
+//
+// Note: This is making the assumption that the timestamp being converted is
+// always in the past. If you call this with a future timestamp, it probably
+// will make it in the past. If you wait over 70 minutes between capturing the
+// bottom 32 bits of the timestamp and expanding it, you will be off by
+// multiples of 1<<32 microseconds.
+//
+// @return The current time in microseconds according to the FPGA (since FPGA
+// reset) as a 64 bit number.
+uint64_t HAL_ExpandFPGATime(uint32_t unexpanded_lower, int32_t* status) {
+ // Capture the current FPGA time. This will give us the upper half of the
+ // clock.
+ uint64_t fpga_time = HAL_GetFPGATime(status);
+ if (*status != 0) return 0;
- wpi_assert(m_interrupt == HAL_kInvalidHandle);
- AllocateInterrupts(false);
- if (StatusIsFatal()) return; // if allocate failed, out of interrupts
+ // Now, we need to detect the case where the lower bits rolled over after we
+ // sampled. In that case, the upper bits will be 1 bigger than they should
+ // be.
- int32_t status = 0;
- HAL_RequestInterrupts(
- m_interrupt, GetPortHandleForRouting(),
- static_cast<HAL_AnalogTriggerType>(GetAnalogTriggerTypeForRouting()),
- &status);
- SetUpSourceEdge(true, false);
- HAL_AttachInterruptHandler(m_interrupt, handler, param, &status);
- wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ // Break it into lower and upper portions.
+ uint32_t lower = fpga_time & ((uint64_t)0xffffffff);
+ uint64_t upper = (fpga_time >> 32) & 0xffffffff;
+
+ // The time was sampled *before* the current time, so roll it back.
+ if (lower < unexpanded_lower) {
+ --upper;
+ }
+
+ return (upper << 32) + static_cast<uint64_t>(unexpanded_lower);
}
-/**
- * Request one of the 8 interrupts synchronously on this digital input.
- *
- * Request interrupts in synchronous mode where the user program will have to
- * explicitly wait for the interrupt to occur using WaitForInterrupt.
- * The default is interrupt on rising edges only.
- */
+} // namespace
+
+InterruptableSensorBase::InterruptableSensorBase() {}
+
void InterruptableSensorBase::RequestInterrupts() {
if (StatusIsFatal()) return;
@@ -72,11 +75,6 @@
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
-/**
- * Cancel interrupts on this device.
- *
- * This deallocates all the chipobject structures and disables any interrupts.
- */
void InterruptableSensorBase::CancelInterrupts() {
if (StatusIsFatal()) return;
wpi_assert(m_interrupt != HAL_kInvalidHandle);
@@ -86,18 +84,6 @@
m_interrupt = HAL_kInvalidHandle;
}
-/**
- * In synchronous mode, wait for the defined interrupt to occur.
- *
- * You should <b>NOT</b> attempt to read the sensor from another thread while
- * waiting for an interrupt. This is not threadsafe, and can cause memory
- * corruption
- *
- * @param timeout Timeout in seconds
- * @param ignorePrevious If true, ignore interrupts that happened before
- * WaitForInterrupt was called.
- * @return What interrupts fired
- */
InterruptableSensorBase::WaitResult InterruptableSensorBase::WaitForInterrupt(
double timeout, bool ignorePrevious) {
if (StatusIsFatal()) return InterruptableSensorBase::kTimeout;
@@ -117,13 +103,6 @@
return static_cast<WaitResult>(falling | rising);
}
-/**
- * Enable interrupts to occur on this input.
- *
- * Interrupts are disabled when the RequestInterrupt call is made. This gives
- * time to do the setup of the other options before starting to field
- * interrupts.
- */
void InterruptableSensorBase::EnableInterrupts() {
if (StatusIsFatal()) return;
wpi_assert(m_interrupt != HAL_kInvalidHandle);
@@ -132,59 +111,26 @@
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
-/**
- * Disable Interrupts without without deallocating structures.
- */
-void InterruptableSensorBase::DisableInterrupts() {
- if (StatusIsFatal()) return;
+hal::fpga_clock::time_point InterruptableSensorBase::ReadRisingTimestamp() {
+ if (StatusIsFatal()) return hal::fpga_clock::min_time;
wpi_assert(m_interrupt != HAL_kInvalidHandle);
int32_t status = 0;
- HAL_DisableInterrupts(m_interrupt, &status);
+ uint64_t timestamp = HAL_ReadInterruptRisingTimestamp(m_interrupt, &status);
+ timestamp = HAL_ExpandFPGATime(timestamp, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return hal::fpga_clock::time_point(hal::fpga_clock::duration(timestamp));
}
-/**
- * Return the timestamp for the rising interrupt that occurred most recently.
- *
- * This is in the same time domain as GetClock().
- * The rising-edge interrupt should be enabled with
- * {@link #DigitalInput.SetUpSourceEdge}
- *
- * @return Timestamp in seconds since boot.
- */
-double InterruptableSensorBase::ReadRisingTimestamp() {
- if (StatusIsFatal()) return 0.0;
+hal::fpga_clock::time_point InterruptableSensorBase::ReadFallingTimestamp() {
+ if (StatusIsFatal()) return hal::fpga_clock::min_time;
wpi_assert(m_interrupt != HAL_kInvalidHandle);
int32_t status = 0;
- double timestamp = HAL_ReadInterruptRisingTimestamp(m_interrupt, &status);
+ uint64_t timestamp = HAL_ReadInterruptFallingTimestamp(m_interrupt, &status);
+ timestamp = HAL_ExpandFPGATime(timestamp, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
- return timestamp;
+ return hal::fpga_clock::time_point(hal::fpga_clock::duration(timestamp));
}
-/**
- * Return the timestamp for the falling interrupt that occurred most recently.
- *
- * This is in the same time domain as GetClock().
- * The falling-edge interrupt should be enabled with
- * {@link #DigitalInput.SetUpSourceEdge}
- *
- * @return Timestamp in seconds since boot.
-*/
-double InterruptableSensorBase::ReadFallingTimestamp() {
- if (StatusIsFatal()) return 0.0;
- wpi_assert(m_interrupt != HAL_kInvalidHandle);
- int32_t status = 0;
- double timestamp = HAL_ReadInterruptFallingTimestamp(m_interrupt, &status);
- wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
- return timestamp;
-}
-
-/**
- * Set which edge to trigger interrupts on
- *
- * @param risingEdge true to interrupt on rising edge
- * @param fallingEdge true to interrupt on falling edge
- */
void InterruptableSensorBase::SetUpSourceEdge(bool risingEdge,
bool fallingEdge) {
if (StatusIsFatal()) return;