blob: d17f2dd34c719e77665b307d472b8b27e05f744f [file] [log] [blame]
Parker Schuhd3b7a8872018-02-19 16:42:27 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008-2017. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "frc971/wpilib/ahal/InterruptableSensorBase.h"
9
Austin Schuhf6b94632019-02-02 22:11:27 -080010#include "hal/HAL.h"
Parker Schuhd3b7a8872018-02-19 16:42:27 -080011#include "frc971/wpilib/ahal/Utility.h"
12#include "frc971/wpilib/ahal/WPIErrors.h"
13
14using namespace frc;
15
Austin Schuhf6b94632019-02-02 22:11:27 -080016InterruptableSensorBase::InterruptableSensorBase() {}
17
Parker Schuhd3b7a8872018-02-19 16:42:27 -080018void InterruptableSensorBase::RequestInterrupts() {
19 if (StatusIsFatal()) return;
20
21 wpi_assert(m_interrupt == HAL_kInvalidHandle);
22 AllocateInterrupts(true);
23 if (StatusIsFatal()) return; // if allocate failed, out of interrupts
24
25 int32_t status = 0;
26 HAL_RequestInterrupts(
27 m_interrupt, GetPortHandleForRouting(),
28 static_cast<HAL_AnalogTriggerType>(GetAnalogTriggerTypeForRouting()),
29 &status);
30 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
31 SetUpSourceEdge(true, false);
32}
33
34void InterruptableSensorBase::AllocateInterrupts(bool watcher) {
35 wpi_assert(m_interrupt == HAL_kInvalidHandle);
36 // Expects the calling leaf class to allocate an interrupt index.
37 int32_t status = 0;
38 m_interrupt = HAL_InitializeInterrupts(watcher, &status);
39 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
40}
41
Parker Schuhd3b7a8872018-02-19 16:42:27 -080042void InterruptableSensorBase::CancelInterrupts() {
43 if (StatusIsFatal()) return;
44 wpi_assert(m_interrupt != HAL_kInvalidHandle);
45 int32_t status = 0;
46 HAL_CleanInterrupts(m_interrupt, &status);
47 // ignore status, as an invalid handle just needs to be ignored.
48 m_interrupt = HAL_kInvalidHandle;
49}
50
Parker Schuhd3b7a8872018-02-19 16:42:27 -080051InterruptableSensorBase::WaitResult InterruptableSensorBase::WaitForInterrupt(
52 double timeout, bool ignorePrevious) {
53 if (StatusIsFatal()) return InterruptableSensorBase::kTimeout;
54 wpi_assert(m_interrupt != HAL_kInvalidHandle);
55 int32_t status = 0;
56 int result;
57
58 result = HAL_WaitForInterrupt(m_interrupt, timeout, ignorePrevious, &status);
59 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
60
61 // Rising edge result is the interrupt bit set in the byte 0xFF
62 // Falling edge result is the interrupt bit set in the byte 0xFF00
63 // Set any bit set to be true for that edge, and AND the 2 results
64 // together to match the existing enum for all interrupts
65 int32_t rising = (result & 0xFF) ? 0x1 : 0x0;
66 int32_t falling = ((result & 0xFF00) ? 0x0100 : 0x0);
67 return static_cast<WaitResult>(falling | rising);
68}
69
Parker Schuhd3b7a8872018-02-19 16:42:27 -080070void InterruptableSensorBase::EnableInterrupts() {
71 if (StatusIsFatal()) return;
72 wpi_assert(m_interrupt != HAL_kInvalidHandle);
73 int32_t status = 0;
74 HAL_EnableInterrupts(m_interrupt, &status);
75 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
76}
77
Austin Schuhf6b94632019-02-02 22:11:27 -080078hal::fpga_clock::time_point InterruptableSensorBase::ReadRisingTimestamp() {
79 if (StatusIsFatal()) return hal::fpga_clock::min_time;
Parker Schuhd3b7a8872018-02-19 16:42:27 -080080 wpi_assert(m_interrupt != HAL_kInvalidHandle);
81 int32_t status = 0;
Austin Schuhf6b94632019-02-02 22:11:27 -080082 uint64_t timestamp = HAL_ReadInterruptRisingTimestamp(m_interrupt, &status);
83 timestamp = HAL_ExpandFPGATime(timestamp, &status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080084 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
Austin Schuhf6b94632019-02-02 22:11:27 -080085 return hal::fpga_clock::time_point(hal::fpga_clock::duration(timestamp));
Parker Schuhd3b7a8872018-02-19 16:42:27 -080086}
87
Austin Schuhf6b94632019-02-02 22:11:27 -080088hal::fpga_clock::time_point InterruptableSensorBase::ReadFallingTimestamp() {
89 if (StatusIsFatal()) return hal::fpga_clock::min_time;
Parker Schuhd3b7a8872018-02-19 16:42:27 -080090 wpi_assert(m_interrupt != HAL_kInvalidHandle);
91 int32_t status = 0;
Austin Schuhf6b94632019-02-02 22:11:27 -080092 uint64_t timestamp = HAL_ReadInterruptFallingTimestamp(m_interrupt, &status);
93 timestamp = HAL_ExpandFPGATime(timestamp, &status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080094 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
Austin Schuhf6b94632019-02-02 22:11:27 -080095 return hal::fpga_clock::time_point(hal::fpga_clock::duration(timestamp));
Parker Schuhd3b7a8872018-02-19 16:42:27 -080096}
97
Parker Schuhd3b7a8872018-02-19 16:42:27 -080098void InterruptableSensorBase::SetUpSourceEdge(bool risingEdge,
99 bool fallingEdge) {
100 if (StatusIsFatal()) return;
101 if (m_interrupt == HAL_kInvalidHandle) {
102 wpi_setWPIErrorWithContext(
103 NullParameter,
104 "You must call RequestInterrupts before SetUpSourceEdge");
105 return;
106 }
107 if (m_interrupt != HAL_kInvalidHandle) {
108 int32_t status = 0;
109 HAL_SetInterruptUpSourceEdge(m_interrupt, risingEdge, fallingEdge, &status);
110 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
111 }
112}