Squashed 'third_party/allwpilib_2019/' content from commit bd05dfa1c

Change-Id: I2b1c2250cdb9b055133780c33593292098c375b7
git-subtree-dir: third_party/allwpilib_2019
git-subtree-split: bd05dfa1c7cca74c4fac451e7b9d6a37e7b53447
diff --git a/hal/src/main/native/sim/AnalogTrigger.cpp b/hal/src/main/native/sim/AnalogTrigger.cpp
new file mode 100644
index 0000000..53b165c
--- /dev/null
+++ b/hal/src/main/native/sim/AnalogTrigger.cpp
@@ -0,0 +1,261 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#include "hal/AnalogTrigger.h"
+
+#include "AnalogInternal.h"
+#include "HALInitializer.h"
+#include "PortsInternal.h"
+#include "hal/AnalogInput.h"
+#include "hal/Errors.h"
+#include "hal/handles/HandlesInternal.h"
+#include "hal/handles/LimitedHandleResource.h"
+#include "mockdata/AnalogInDataInternal.h"
+#include "mockdata/AnalogTriggerDataInternal.h"
+
+namespace {
+struct AnalogTrigger {
+  HAL_AnalogInputHandle analogHandle;
+  uint8_t index;
+  HAL_Bool trigState;
+};
+}  // namespace
+
+using namespace hal;
+
+static LimitedHandleResource<HAL_AnalogTriggerHandle, AnalogTrigger,
+                             kNumAnalogTriggers, HAL_HandleEnum::AnalogTrigger>*
+    analogTriggerHandles;
+
+namespace hal {
+namespace init {
+void InitializeAnalogTrigger() {
+  static LimitedHandleResource<HAL_AnalogTriggerHandle, AnalogTrigger,
+                               kNumAnalogTriggers,
+                               HAL_HandleEnum::AnalogTrigger>
+      atH;
+  analogTriggerHandles = &atH;
+}
+}  // namespace init
+}  // namespace hal
+
+int32_t hal::GetAnalogTriggerInputIndex(HAL_AnalogTriggerHandle handle,
+                                        int32_t* status) {
+  auto trigger = analogTriggerHandles->Get(handle);
+  if (trigger == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  auto analog_port = analogInputHandles->Get(trigger->analogHandle);
+  if (analog_port == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  return analog_port->channel;
+}
+
+extern "C" {
+
+HAL_AnalogTriggerHandle HAL_InitializeAnalogTrigger(
+    HAL_AnalogInputHandle portHandle, int32_t* index, int32_t* status) {
+  hal::init::CheckInit();
+  // ensure we are given a valid and active AnalogInput handle
+  auto analog_port = analogInputHandles->Get(portHandle);
+  if (analog_port == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return HAL_kInvalidHandle;
+  }
+  HAL_AnalogTriggerHandle handle = analogTriggerHandles->Allocate();
+  if (handle == HAL_kInvalidHandle) {
+    *status = NO_AVAILABLE_RESOURCES;
+    return HAL_kInvalidHandle;
+  }
+  auto trigger = analogTriggerHandles->Get(handle);
+  if (trigger == nullptr) {  // would only occur on thread issue
+    *status = HAL_HANDLE_ERROR;
+    return HAL_kInvalidHandle;
+  }
+  trigger->analogHandle = portHandle;
+  trigger->index = static_cast<uint8_t>(getHandleIndex(handle));
+  *index = trigger->index;
+
+  SimAnalogTriggerData[trigger->index].initialized = true;
+
+  trigger->trigState = false;
+
+  return handle;
+}
+
+void HAL_CleanAnalogTrigger(HAL_AnalogTriggerHandle analogTriggerHandle,
+                            int32_t* status) {
+  auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
+  analogTriggerHandles->Free(analogTriggerHandle);
+  if (trigger == nullptr) return;
+  SimAnalogTriggerData[trigger->index].initialized = false;
+  // caller owns the analog input handle.
+}
+
+static double GetAnalogValueToVoltage(
+    HAL_AnalogTriggerHandle analogTriggerHandle, int32_t value,
+    int32_t* status) {
+  int32_t LSBWeight = HAL_GetAnalogLSBWeight(analogTriggerHandle, status);
+  int32_t offset = HAL_GetAnalogOffset(analogTriggerHandle, status);
+
+  double voltage = LSBWeight * 1.0e-9 * value - offset * 1.0e-9;
+  return voltage;
+}
+
+void HAL_SetAnalogTriggerLimitsRaw(HAL_AnalogTriggerHandle analogTriggerHandle,
+                                   int32_t lower, int32_t upper,
+                                   int32_t* status) {
+  auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
+  if (trigger == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+  if (lower > upper) {
+    *status = ANALOG_TRIGGER_LIMIT_ORDER_ERROR;
+  }
+
+  double trigLower =
+      GetAnalogValueToVoltage(trigger->analogHandle, lower, status);
+  if (status != 0) return;
+  double trigUpper =
+      GetAnalogValueToVoltage(trigger->analogHandle, upper, status);
+  if (status != 0) return;
+
+  SimAnalogTriggerData[trigger->index].triggerUpperBound = trigUpper;
+  SimAnalogTriggerData[trigger->index].triggerLowerBound = trigLower;
+}
+void HAL_SetAnalogTriggerLimitsVoltage(
+    HAL_AnalogTriggerHandle analogTriggerHandle, double lower, double upper,
+    int32_t* status) {
+  auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
+  if (trigger == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+  if (lower > upper) {
+    *status = ANALOG_TRIGGER_LIMIT_ORDER_ERROR;
+  }
+
+  SimAnalogTriggerData[trigger->index].triggerUpperBound = upper;
+  SimAnalogTriggerData[trigger->index].triggerLowerBound = lower;
+}
+void HAL_SetAnalogTriggerAveraged(HAL_AnalogTriggerHandle analogTriggerHandle,
+                                  HAL_Bool useAveragedValue, int32_t* status) {
+  auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
+  if (trigger == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  AnalogTriggerData* triggerData = &SimAnalogTriggerData[trigger->index];
+
+  if (triggerData->triggerMode.Get() == HALSIM_AnalogTriggerFiltered) {
+    *status = INCOMPATIBLE_STATE;
+    return;
+  }
+
+  auto setVal = useAveragedValue ? HALSIM_AnalogTriggerAveraged
+                                 : HALSIM_AnalogTriggerUnassigned;
+  triggerData->triggerMode = setVal;
+}
+void HAL_SetAnalogTriggerFiltered(HAL_AnalogTriggerHandle analogTriggerHandle,
+                                  HAL_Bool useFilteredValue, int32_t* status) {
+  auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
+  if (trigger == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  AnalogTriggerData* triggerData = &SimAnalogTriggerData[trigger->index];
+
+  if (triggerData->triggerMode.Get() == HALSIM_AnalogTriggerAveraged) {
+    *status = INCOMPATIBLE_STATE;
+    return;
+  }
+
+  auto setVal = useFilteredValue ? HALSIM_AnalogTriggerAveraged
+                                 : HALSIM_AnalogTriggerUnassigned;
+  triggerData->triggerMode = setVal;
+}
+
+static double GetTriggerValue(AnalogTrigger* trigger, int32_t* status) {
+  auto analogIn = analogInputHandles->Get(trigger->analogHandle);
+  if (analogIn == nullptr) {
+    // Returning HAL Handle Error, but going to ignore lower down
+    *status = HAL_HANDLE_ERROR;
+    return 0.0;
+  }
+
+  return SimAnalogInData[analogIn->channel].voltage;
+}
+
+HAL_Bool HAL_GetAnalogTriggerInWindow(
+    HAL_AnalogTriggerHandle analogTriggerHandle, int32_t* status) {
+  auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
+  if (trigger == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return false;
+  }
+
+  double voltage = GetTriggerValue(trigger.get(), status);
+  if (*status == HAL_HANDLE_ERROR) {
+    // Don't error if analog has been destroyed
+    *status = 0;
+    return false;
+  }
+
+  double trigUpper = SimAnalogTriggerData[trigger->index].triggerUpperBound;
+  double trigLower = SimAnalogTriggerData[trigger->index].triggerLowerBound;
+
+  return voltage >= trigLower && voltage <= trigUpper;
+}
+HAL_Bool HAL_GetAnalogTriggerTriggerState(
+    HAL_AnalogTriggerHandle analogTriggerHandle, int32_t* status) {
+  auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
+  if (trigger == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return false;
+  }
+
+  double voltage = GetTriggerValue(trigger.get(), status);
+  if (*status == HAL_HANDLE_ERROR) {
+    // Don't error if analog has been destroyed
+    *status = 0;
+    return false;
+  }
+
+  double trigUpper = SimAnalogTriggerData[trigger->index].triggerUpperBound;
+  double trigLower = SimAnalogTriggerData[trigger->index].triggerLowerBound;
+
+  if (voltage < trigLower) {
+    trigger->trigState = false;
+    return false;
+  }
+  if (voltage > trigUpper) {
+    trigger->trigState = true;
+    return true;
+  }
+  return trigger->trigState;
+}
+HAL_Bool HAL_GetAnalogTriggerOutput(HAL_AnalogTriggerHandle analogTriggerHandle,
+                                    HAL_AnalogTriggerType type,
+                                    int32_t* status) {
+  if (type == HAL_Trigger_kInWindow) {
+    return HAL_GetAnalogTriggerInWindow(analogTriggerHandle, status);
+  } else if (type == HAL_Trigger_kState) {
+    return HAL_GetAnalogTriggerTriggerState(analogTriggerHandle, status);
+  } else {
+    *status = ANALOG_TRIGGER_PULSE_OUTPUT_ERROR;
+    return false;
+  }
+}
+}  // extern "C"