blob: 59eb962ceb88b9e324fa9b09e1b2d7b9052537f9 [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
Parker Schuhd3b7a8872018-02-19 16:42:27 -080010#include "frc971/wpilib/ahal/WPIErrors.h"
Austin Schuh9950f682021-11-06 15:27:58 -070011#include "glog/logging.h"
12#include "hal/HAL.h"
Parker Schuhd3b7a8872018-02-19 16:42:27 -080013
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
Austin Schuh9950f682021-11-06 15:27:58 -070021 CHECK_EQ(m_interrupt, HAL_kInvalidHandle);
22 AllocateInterrupts();
Parker Schuhd3b7a8872018-02-19 16:42:27 -080023 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
Austin Schuh9950f682021-11-06 15:27:58 -070034void InterruptableSensorBase::AllocateInterrupts() {
35 CHECK_EQ(m_interrupt, HAL_kInvalidHandle);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080036 // Expects the calling leaf class to allocate an interrupt index.
37 int32_t status = 0;
Austin Schuh9950f682021-11-06 15:27:58 -070038 m_interrupt = HAL_InitializeInterrupts(&status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080039 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
40}
41
Parker Schuhd3b7a8872018-02-19 16:42:27 -080042void InterruptableSensorBase::CancelInterrupts() {
43 if (StatusIsFatal()) return;
Austin Schuh9950f682021-11-06 15:27:58 -070044 CHECK_NE(m_interrupt, HAL_kInvalidHandle);
45 HAL_CleanInterrupts(m_interrupt);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080046 // ignore status, as an invalid handle just needs to be ignored.
47 m_interrupt = HAL_kInvalidHandle;
48}
49
Parker Schuhd3b7a8872018-02-19 16:42:27 -080050InterruptableSensorBase::WaitResult InterruptableSensorBase::WaitForInterrupt(
51 double timeout, bool ignorePrevious) {
52 if (StatusIsFatal()) return InterruptableSensorBase::kTimeout;
Austin Schuh9950f682021-11-06 15:27:58 -070053 CHECK_NE(m_interrupt, HAL_kInvalidHandle);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080054 int32_t status = 0;
55 int result;
56
57 result = HAL_WaitForInterrupt(m_interrupt, timeout, ignorePrevious, &status);
58 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
59
60 // Rising edge result is the interrupt bit set in the byte 0xFF
61 // Falling edge result is the interrupt bit set in the byte 0xFF00
62 // Set any bit set to be true for that edge, and AND the 2 results
63 // together to match the existing enum for all interrupts
64 int32_t rising = (result & 0xFF) ? 0x1 : 0x0;
65 int32_t falling = ((result & 0xFF00) ? 0x0100 : 0x0);
66 return static_cast<WaitResult>(falling | rising);
67}
68
Austin Schuhf6b94632019-02-02 22:11:27 -080069hal::fpga_clock::time_point InterruptableSensorBase::ReadRisingTimestamp() {
70 if (StatusIsFatal()) return hal::fpga_clock::min_time;
Austin Schuh9950f682021-11-06 15:27:58 -070071 CHECK_NE(m_interrupt, HAL_kInvalidHandle);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080072 int32_t status = 0;
Austin Schuhf6b94632019-02-02 22:11:27 -080073 uint64_t timestamp = HAL_ReadInterruptRisingTimestamp(m_interrupt, &status);
74 timestamp = HAL_ExpandFPGATime(timestamp, &status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080075 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
Austin Schuhf6b94632019-02-02 22:11:27 -080076 return hal::fpga_clock::time_point(hal::fpga_clock::duration(timestamp));
Parker Schuhd3b7a8872018-02-19 16:42:27 -080077}
78
Austin Schuhf6b94632019-02-02 22:11:27 -080079hal::fpga_clock::time_point InterruptableSensorBase::ReadFallingTimestamp() {
80 if (StatusIsFatal()) return hal::fpga_clock::min_time;
Austin Schuh9950f682021-11-06 15:27:58 -070081 CHECK_NE(m_interrupt, HAL_kInvalidHandle);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080082 int32_t status = 0;
Austin Schuhf6b94632019-02-02 22:11:27 -080083 uint64_t timestamp = HAL_ReadInterruptFallingTimestamp(m_interrupt, &status);
84 timestamp = HAL_ExpandFPGATime(timestamp, &status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080085 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
Austin Schuhf6b94632019-02-02 22:11:27 -080086 return hal::fpga_clock::time_point(hal::fpga_clock::duration(timestamp));
Parker Schuhd3b7a8872018-02-19 16:42:27 -080087}
88
Parker Schuhd3b7a8872018-02-19 16:42:27 -080089void InterruptableSensorBase::SetUpSourceEdge(bool risingEdge,
90 bool fallingEdge) {
91 if (StatusIsFatal()) return;
92 if (m_interrupt == HAL_kInvalidHandle) {
93 wpi_setWPIErrorWithContext(
94 NullParameter,
95 "You must call RequestInterrupts before SetUpSourceEdge");
96 return;
97 }
98 if (m_interrupt != HAL_kInvalidHandle) {
99 int32_t status = 0;
100 HAL_SetInterruptUpSourceEdge(m_interrupt, risingEdge, fallingEdge, &status);
101 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
102 }
103}