blob: 49acd84f6a31ee2719c0625cfce314b05662eca2 [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#include "frc/SynchronousInterrupt.h"
6
7#include <type_traits>
8
9#include <hal/Interrupts.h>
10#include <wpi/NullDeleter.h>
11
12#include "frc/DigitalSource.h"
13#include "frc/Errors.h"
14
15using namespace frc;
16
17SynchronousInterrupt::SynchronousInterrupt(DigitalSource& source)
18 : m_source{&source, wpi::NullDeleter<DigitalSource>()} {
19 InitSynchronousInterrupt();
20}
21SynchronousInterrupt::SynchronousInterrupt(DigitalSource* source)
22 : m_source{source, wpi::NullDeleter<DigitalSource>()} {
23 if (m_source == nullptr) {
24 FRC_CheckErrorStatus(frc::err::NullParameter, "{}", "Source is null");
25 } else {
26 InitSynchronousInterrupt();
27 }
28}
29SynchronousInterrupt::SynchronousInterrupt(
30 std::shared_ptr<DigitalSource> source)
31 : m_source{std::move(source)} {
32 if (m_source == nullptr) {
33 FRC_CheckErrorStatus(frc::err::NullParameter, "{}", "Source is null");
34 } else {
35 InitSynchronousInterrupt();
36 }
37}
38
39void SynchronousInterrupt::InitSynchronousInterrupt() {
40 int32_t status = 0;
41 m_handle = HAL_InitializeInterrupts(&status);
42 FRC_CheckErrorStatus(status, "{}", "Interrupt failed to initialize");
43 HAL_RequestInterrupts(m_handle, m_source->GetPortHandleForRouting(),
44 static_cast<HAL_AnalogTriggerType>(
45 m_source->GetAnalogTriggerTypeForRouting()),
46 &status);
47 FRC_CheckErrorStatus(status, "{}", "Interrupt request failed");
48 HAL_SetInterruptUpSourceEdge(m_handle, true, false, &status);
49 FRC_CheckErrorStatus(status, "{}", "Interrupt setting up source edge failed");
50}
51
52SynchronousInterrupt::~SynchronousInterrupt() {
53 HAL_CleanInterrupts(m_handle);
54}
55
56inline SynchronousInterrupt::WaitResult operator|(
57 SynchronousInterrupt::WaitResult lhs,
58 SynchronousInterrupt::WaitResult rhs) {
59 using T = std::underlying_type_t<SynchronousInterrupt::WaitResult>;
60 return static_cast<SynchronousInterrupt::WaitResult>(static_cast<T>(lhs) |
61 static_cast<T>(rhs));
62}
63
64SynchronousInterrupt::WaitResult SynchronousInterrupt::WaitForInterrupt(
65 units::second_t timeout, bool ignorePrevious) {
66 int32_t status = 0;
67 auto result =
68 HAL_WaitForInterrupt(m_handle, timeout.value(), ignorePrevious, &status);
69
70 auto rising =
71 ((result & 0xFF) != 0) ? WaitResult::kRisingEdge : WaitResult::kTimeout;
72 auto falling = ((result & 0xFF00) != 0) ? WaitResult::kFallingEdge
73 : WaitResult::kTimeout;
74
75 return rising | falling;
76}
77
78void SynchronousInterrupt::SetInterruptEdges(bool risingEdge,
79 bool fallingEdge) {
80 int32_t status = 0;
81 HAL_SetInterruptUpSourceEdge(m_handle, risingEdge, fallingEdge, &status);
82 FRC_CheckErrorStatus(status, "{}", "Interrupt setting edges failed");
83}
84
85void SynchronousInterrupt::WakeupWaitingInterrupt() {
86 int32_t status = 0;
87 HAL_ReleaseWaitingInterrupt(m_handle, &status);
88 FRC_CheckErrorStatus(status, "{}", "Interrupt wakeup failed");
89}
90
91units::second_t SynchronousInterrupt::GetRisingTimestamp() {
92 int32_t status = 0;
93 auto ts = HAL_ReadInterruptRisingTimestamp(m_handle, &status);
94 FRC_CheckErrorStatus(status, "{}", "Interrupt rising timestamp failed");
95 units::microsecond_t ms{static_cast<double>(ts)};
96 return ms;
97}
98
99units::second_t SynchronousInterrupt::GetFallingTimestamp() {
100 int32_t status = 0;
101 auto ts = HAL_ReadInterruptFallingTimestamp(m_handle, &status);
102 FRC_CheckErrorStatus(status, "{}", "Interrupt falling timestamp failed");
103 units::microsecond_t ms{static_cast<double>(ts)};
104 return ms;
105}