Add lambda overloads for interrupts (#1636)

This commit is contained in:
Thad House
2019-05-30 17:59:35 -07:00
committed by Peter Johnson
parent 90957aeea4
commit 7de9477347
3 changed files with 141 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2008-2018 FIRST. All Rights Reserved. */
/* Copyright (c) 2008-2019 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. */
@@ -14,6 +14,32 @@
using namespace frc;
InterruptableSensorBase::~InterruptableSensorBase() {
if (m_interrupt == HAL_kInvalidHandle) return;
int32_t status = 0;
auto param = HAL_CleanInterrupts(m_interrupt, &status);
if (param) {
delete reinterpret_cast<InterruptEventHandler*>(param);
}
// Ignore status, as an invalid handle just needs to be ignored.
m_interrupt = HAL_kInvalidHandle;
}
InterruptableSensorBase::InterruptableSensorBase(InterruptableSensorBase&& rhs)
: ErrorBase(std::move(rhs)),
m_interrupt(rhs.m_interrupt.exchange(HAL_kInvalidHandle)) {
rhs.m_interrupt = HAL_kInvalidHandle;
}
InterruptableSensorBase& InterruptableSensorBase::operator=(
InterruptableSensorBase&& rhs) {
ErrorBase::operator=(std::move(rhs));
m_interrupt = rhs.m_interrupt.exchange(HAL_kInvalidHandle);
return *this;
}
void InterruptableSensorBase::RequestInterrupts(
HAL_InterruptHandlerFunction handler, void* param) {
if (StatusIsFatal()) return;
@@ -32,6 +58,38 @@ void InterruptableSensorBase::RequestInterrupts(
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void InterruptableSensorBase::RequestInterrupts(InterruptEventHandler handler) {
if (StatusIsFatal()) return;
wpi_assert(m_interrupt == HAL_kInvalidHandle);
AllocateInterrupts(false);
if (StatusIsFatal()) return; // if allocate failed, out of interrupts
auto handlerPtr = new InterruptEventHandler(std::move(handler));
int32_t status = 0;
HAL_RequestInterrupts(
m_interrupt, GetPortHandleForRouting(),
static_cast<HAL_AnalogTriggerType>(GetAnalogTriggerTypeForRouting()),
&status);
SetUpSourceEdge(true, false);
HAL_AttachInterruptHandler(
m_interrupt,
[](uint32_t mask, void* param) {
auto self = reinterpret_cast<InterruptEventHandler*>(param);
// Rising edge result is the interrupt bit set in the byte 0xFF
// Falling edge result is the interrupt bit set in the byte 0xFF00
// Set any bit set to be true for that edge, and AND the 2 results
// together to match the existing enum for all interrupts
int32_t rising = (mask & 0xFF) ? 0x1 : 0x0;
int32_t falling = ((mask & 0xFF00) ? 0x0100 : 0x0);
WaitResult res = static_cast<WaitResult>(falling | rising);
(*self)(res);
},
handlerPtr, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void InterruptableSensorBase::RequestInterrupts() {
if (StatusIsFatal()) return;
@@ -52,7 +110,10 @@ void InterruptableSensorBase::CancelInterrupts() {
if (StatusIsFatal()) return;
wpi_assert(m_interrupt != HAL_kInvalidHandle);
int32_t status = 0;
HAL_CleanInterrupts(m_interrupt, &status);
auto param = HAL_CleanInterrupts(m_interrupt, &status);
if (param) {
delete reinterpret_cast<InterruptEventHandler*>(param);
}
// Ignore status, as an invalid handle just needs to be ignored.
m_interrupt = HAL_kInvalidHandle;
}