mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
[wpilib] Remove InterruptableSensorBase and replace with interrupt classes (#2410)
This commit is contained in:
150
wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h
Normal file
150
wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <frc/SynchronousInterrupt.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
namespace frc {
|
||||
/**
|
||||
* Class for handling asynchronous interrupts.
|
||||
*
|
||||
* <p> By default, interrupts will occur on rising edge. Callbacks are disabled
|
||||
* by default, and Enable() must be called before they will occur.
|
||||
*
|
||||
* <p> Both rising and falling edge can be indiciated if both a rising and
|
||||
* falling happen between callbacks.
|
||||
*
|
||||
* <p>Synchronous interrupts are handled by the SynchronousInterrupt class.
|
||||
*/
|
||||
class AsynchronousInterrupt {
|
||||
public:
|
||||
/**
|
||||
* Construct an Asynchronous Interrupt from a Digital Source.
|
||||
*
|
||||
* <p> At construction, the interrupt will trigger on the rising edge.
|
||||
*
|
||||
* <p> The first bool in the callback is rising, the 2nd is falling.
|
||||
*/
|
||||
AsynchronousInterrupt(DigitalSource& source,
|
||||
std::function<void(bool, bool)> callback);
|
||||
|
||||
/**
|
||||
* Construct an Asynchronous Interrupt from a Digital Source.
|
||||
*
|
||||
* <p> At construction, the interrupt will trigger on the rising edge.
|
||||
*
|
||||
* <p> The first bool in the callback is rising, the 2nd is falling.
|
||||
*/
|
||||
AsynchronousInterrupt(DigitalSource* source,
|
||||
std::function<void(bool, bool)> callback);
|
||||
|
||||
/**
|
||||
* Construct an Asynchronous Interrupt from a Digital Source.
|
||||
*
|
||||
* <p> At construction, the interrupt will trigger on the rising edge.
|
||||
*
|
||||
* <p> The first bool in the callback is rising, the 2nd is falling.
|
||||
*/
|
||||
AsynchronousInterrupt(std::shared_ptr<DigitalSource> source,
|
||||
std::function<void(bool, bool)> callback);
|
||||
|
||||
/**
|
||||
* Construct an Asynchronous Interrupt from a Digital Source.
|
||||
*
|
||||
* <p> At construction, the interrupt will trigger on the rising edge.
|
||||
*
|
||||
* <p> The first bool in the callback is rising, the 2nd is falling.
|
||||
*/
|
||||
template <typename Callable, typename Arg, typename... Args>
|
||||
AsynchronousInterrupt(DigitalSource& source, Callable&& f, Arg&& arg,
|
||||
Args&&... args)
|
||||
: AsynchronousInterrupt(
|
||||
source, std::bind(std::forward<Callable>(f), std::forward<Arg>(arg),
|
||||
std::forward<Args>(args)...)) {}
|
||||
|
||||
/**
|
||||
* Construct an Asynchronous Interrupt from a Digital Source.
|
||||
*
|
||||
* <p> At construction, the interrupt will trigger on the rising edge.
|
||||
*
|
||||
* <p> The first bool in the callback is rising, the 2nd is falling.
|
||||
*/
|
||||
template <typename Callable, typename Arg, typename... Args>
|
||||
AsynchronousInterrupt(DigitalSource* source, Callable&& f, Arg&& arg,
|
||||
Args&&... args)
|
||||
: AsynchronousInterrupt(
|
||||
source, std::bind(std::forward<Callable>(f), std::forward<Arg>(arg),
|
||||
std::forward<Args>(args)...)) {}
|
||||
|
||||
/**
|
||||
* Construct an Asynchronous Interrupt from a Digital Source.
|
||||
*
|
||||
* <p> At construction, the interrupt will trigger on the rising edge.
|
||||
*
|
||||
* <p> The first bool in the callback is rising, the 2nd is falling.
|
||||
*/
|
||||
template <typename Callable, typename Arg, typename... Args>
|
||||
AsynchronousInterrupt(std::shared_ptr<DigitalSource> source, Callable&& f,
|
||||
Arg&& arg, Args&&... args)
|
||||
: AsynchronousInterrupt(
|
||||
source, std::bind(std::forward<Callable>(f), std::forward<Arg>(arg),
|
||||
std::forward<Args>(args)...)) {}
|
||||
|
||||
~AsynchronousInterrupt();
|
||||
|
||||
/**
|
||||
* Enables interrupt callbacks. Before this, callbacks will not occur. Does
|
||||
* nothing if already enabled.
|
||||
*/
|
||||
void Enable();
|
||||
|
||||
/**
|
||||
* Disables interrupt callbacks. Does nothing if already disabled.
|
||||
*/
|
||||
void Disable();
|
||||
|
||||
/**
|
||||
* Set which edges to trigger the interrupt on.
|
||||
*
|
||||
* @param risingEdge Trigger on rising edge
|
||||
* @param fallingEdge Trigger on falling edge
|
||||
*/
|
||||
void SetInterruptEdges(bool risingEdge, bool fallingEdge);
|
||||
|
||||
/**
|
||||
* Get the timestamp of the last rising edge.
|
||||
*
|
||||
* <p>This function does not require the interrupt to be enabled to work.
|
||||
*
|
||||
* <p>This only works if rising edge was configured using SetInterruptEdges.
|
||||
* @return the timestamp in seconds relative to getFPGATime
|
||||
*/
|
||||
units::second_t GetRisingTimestamp();
|
||||
|
||||
/**
|
||||
* Get the timestamp of the last falling edge.
|
||||
*
|
||||
* <p>This function does not require the interrupt to be enabled to work.
|
||||
*
|
||||
* <p>This only works if falling edge was configured using SetInterruptEdges.
|
||||
* @return the timestamp in seconds relative to getFPGATime
|
||||
*/
|
||||
units::second_t GetFallingTimestamp();
|
||||
|
||||
private:
|
||||
void ThreadMain();
|
||||
|
||||
std::atomic_bool m_keepRunning{false};
|
||||
std::thread m_thread;
|
||||
SynchronousInterrupt m_interrupt;
|
||||
std::function<void(bool, bool)> m_callback;
|
||||
};
|
||||
} // namespace frc
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <hal/Types.h>
|
||||
|
||||
#include "frc/InterruptableSensorBase.h"
|
||||
#include "frc/AnalogTriggerType.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
@@ -19,14 +19,14 @@ namespace frc {
|
||||
* constructed and freed when finished for the source. The source can either be
|
||||
* a digital input or analog trigger but not both.
|
||||
*/
|
||||
class DigitalSource : public InterruptableSensorBase {
|
||||
class DigitalSource {
|
||||
public:
|
||||
DigitalSource() = default;
|
||||
DigitalSource(DigitalSource&&) = default;
|
||||
DigitalSource& operator=(DigitalSource&&) = default;
|
||||
|
||||
HAL_Handle GetPortHandleForRouting() const override = 0;
|
||||
AnalogTriggerType GetAnalogTriggerTypeForRouting() const override = 0;
|
||||
virtual HAL_Handle GetPortHandleForRouting() const = 0;
|
||||
virtual AnalogTriggerType GetAnalogTriggerTypeForRouting() const = 0;
|
||||
virtual bool IsAnalogTrigger() const = 0;
|
||||
virtual int GetChannel() const = 0;
|
||||
};
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <hal/Interrupts.h>
|
||||
#include <units/time.h>
|
||||
|
||||
#include "frc/AnalogTriggerType.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
class InterruptableSensorBase {
|
||||
public:
|
||||
enum WaitResult {
|
||||
kTimeout = 0x0,
|
||||
kRisingEdge = 0x1,
|
||||
kFallingEdge = 0x100,
|
||||
kBoth = 0x101,
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for interrupts.
|
||||
*
|
||||
* First parameter is if rising, 2nd is if falling.
|
||||
*/
|
||||
using InterruptEventHandler = std::function<void(WaitResult)>;
|
||||
|
||||
InterruptableSensorBase() = default;
|
||||
|
||||
/**
|
||||
* Free the resources for an interrupt event.
|
||||
*/
|
||||
virtual ~InterruptableSensorBase();
|
||||
|
||||
InterruptableSensorBase(InterruptableSensorBase&&) = default;
|
||||
InterruptableSensorBase& operator=(InterruptableSensorBase&&) = default;
|
||||
|
||||
virtual HAL_Handle GetPortHandleForRouting() const = 0;
|
||||
virtual AnalogTriggerType GetAnalogTriggerTypeForRouting() const = 0;
|
||||
|
||||
/**
|
||||
* Request one of the 8 interrupts asynchronously on this digital input.
|
||||
*
|
||||
* Request interrupts in asynchronous mode where the user's interrupt handler
|
||||
* will be called when the interrupt fires. Users that want control over the
|
||||
* thread priority should use the synchronous method with their own spawned
|
||||
* thread. The default is interrupt on rising edges only.
|
||||
*/
|
||||
virtual void RequestInterrupts(HAL_InterruptHandlerFunction handler,
|
||||
void* param);
|
||||
|
||||
/**
|
||||
* Request one of the 8 interrupts asynchronously on this digital input.
|
||||
*
|
||||
* Request interrupts in asynchronous mode where the user's interrupt handler
|
||||
* will be called when the interrupt fires. Users that want control over the
|
||||
* thread priority should use the synchronous method with their own spawned
|
||||
* thread. The default is interrupt on rising edges only.
|
||||
*/
|
||||
virtual void RequestInterrupts(InterruptEventHandler handler);
|
||||
|
||||
/**
|
||||
* Request one of the 8 interrupts synchronously on this digital input.
|
||||
*
|
||||
* Request interrupts in synchronous mode where the user program will have to
|
||||
* explicitly wait for the interrupt to occur using WaitForInterrupt.
|
||||
* The default is interrupt on rising edges only.
|
||||
*/
|
||||
virtual void RequestInterrupts();
|
||||
|
||||
/**
|
||||
* Cancel interrupts on this device.
|
||||
*
|
||||
* This deallocates all the chipobject structures and disables any interrupts.
|
||||
*/
|
||||
virtual void CancelInterrupts();
|
||||
|
||||
/**
|
||||
* In synchronous mode, wait for the defined interrupt to occur.
|
||||
*
|
||||
* You should <b>NOT</b> attempt to read the sensor from another thread while
|
||||
* waiting for an interrupt. This is not threadsafe, and can cause memory
|
||||
* corruption
|
||||
*
|
||||
* @param timeout Timeout
|
||||
* @param ignorePrevious If true, ignore interrupts that happened before
|
||||
* WaitForInterrupt was called.
|
||||
* @return What interrupts fired
|
||||
*/
|
||||
virtual WaitResult WaitForInterrupt(units::second_t timeout,
|
||||
bool ignorePrevious = true);
|
||||
|
||||
/**
|
||||
* Enable interrupts to occur on this input.
|
||||
*
|
||||
* Interrupts are disabled when the RequestInterrupt call is made. This gives
|
||||
* time to do the setup of the other options before starting to field
|
||||
* interrupts.
|
||||
*/
|
||||
virtual void EnableInterrupts();
|
||||
|
||||
/**
|
||||
* Disable Interrupts without without deallocating structures.
|
||||
*/
|
||||
virtual void DisableInterrupts();
|
||||
|
||||
/**
|
||||
* Return the timestamp for the rising interrupt that occurred most recently.
|
||||
*
|
||||
* This is in the same time domain as GetClock(). The rising-edge interrupt
|
||||
* should be enabled with SetUpSourceEdge().
|
||||
*
|
||||
* @return Timestamp in seconds since boot.
|
||||
*/
|
||||
virtual units::second_t ReadRisingTimestamp();
|
||||
|
||||
/**
|
||||
* Return the timestamp for the falling interrupt that occurred most recently.
|
||||
*
|
||||
* This is in the same time domain as GetClock().
|
||||
* The falling-edge interrupt should be enabled with
|
||||
* {@link #DigitalInput.SetUpSourceEdge}
|
||||
*
|
||||
* @return Timestamp in seconds since boot.
|
||||
*/
|
||||
virtual units::second_t ReadFallingTimestamp();
|
||||
|
||||
/**
|
||||
* Set which edge to trigger interrupts on
|
||||
*
|
||||
* @param risingEdge true to interrupt on rising edge
|
||||
* @param fallingEdge true to interrupt on falling edge
|
||||
*/
|
||||
virtual void SetUpSourceEdge(bool risingEdge, bool fallingEdge);
|
||||
|
||||
protected:
|
||||
hal::Handle<HAL_InterruptHandle> m_interrupt;
|
||||
std::unique_ptr<InterruptEventHandler> m_interruptHandler{nullptr};
|
||||
|
||||
void AllocateInterrupts(bool watcher);
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
98
wpilibc/src/main/native/include/frc/SynchronousInterrupt.h
Normal file
98
wpilibc/src/main/native/include/frc/SynchronousInterrupt.h
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <hal/Types.h>
|
||||
#include <units/time.h>
|
||||
|
||||
namespace frc {
|
||||
class DigitalSource;
|
||||
|
||||
/**
|
||||
* Class for handling ssynchronous interrupts.
|
||||
*
|
||||
* <p> By default, interrupts will occur on rising edge.
|
||||
*
|
||||
* <p> Asynchronous interrupts are handled by the AsynchronousInterrupt class.
|
||||
*/
|
||||
class SynchronousInterrupt {
|
||||
public:
|
||||
enum WaitResult {
|
||||
kTimeout = 0x0,
|
||||
kRisingEdge = 0x1,
|
||||
kFallingEdge = 0x100,
|
||||
kBoth = 0x101,
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a Synchronous Interrupt from a Digital Source.
|
||||
*/
|
||||
explicit SynchronousInterrupt(DigitalSource& source);
|
||||
|
||||
/**
|
||||
* Construct a Synchronous Interrupt from a Digital Source.
|
||||
*/
|
||||
explicit SynchronousInterrupt(DigitalSource* source);
|
||||
|
||||
/**
|
||||
* Construct a Synchronous Interrupt from a Digital Source.
|
||||
*/
|
||||
explicit SynchronousInterrupt(std::shared_ptr<DigitalSource> source);
|
||||
|
||||
~SynchronousInterrupt();
|
||||
|
||||
SynchronousInterrupt(SynchronousInterrupt&&) = default;
|
||||
SynchronousInterrupt& operator=(SynchronousInterrupt&&) = default;
|
||||
|
||||
/**
|
||||
* Wait for an interrupt to occur.
|
||||
*
|
||||
* <p> Both rising and falling edge can be returned if both a rising and
|
||||
* falling happened between calls, and ignorePrevious is false.
|
||||
*
|
||||
* @param timeout The timeout to wait for. 0s or less will return immediately.
|
||||
* @param ignorePrevious True to ignore any previous interrupts, false to
|
||||
* return interrupt value if an interrupt has occured since last call.
|
||||
* @return The edge(s) that were triggered, or timeout.
|
||||
*/
|
||||
WaitResult WaitForInterrupt(units::second_t timeout,
|
||||
bool ignorePrevious = true);
|
||||
|
||||
/**
|
||||
* Set which edges cause an interrupt to occur.
|
||||
*
|
||||
* @param risingEdge true to trigger on rising edge, false otherwise.
|
||||
* @param fallingEdge true to trigger on falling edge, false otherwise
|
||||
*/
|
||||
void SetInterruptEdges(bool risingEdge, bool fallingEdge);
|
||||
|
||||
/**
|
||||
* Get the timestamp (relative to FPGA Time) of the last rising edge.
|
||||
*/
|
||||
units::second_t GetRisingTimestamp();
|
||||
|
||||
/**
|
||||
* Get the timestamp of the last falling edge.
|
||||
*
|
||||
* <p>This function does not require the interrupt to be enabled to work.
|
||||
*
|
||||
* <p>This only works if falling edge was configured using setInterruptEdges.
|
||||
* @return the timestamp in seconds relative to getFPGATime
|
||||
*/
|
||||
units::second_t GetFallingTimestamp();
|
||||
|
||||
/**
|
||||
* Wake up an existing wait call. Can be called from any thread.
|
||||
*/
|
||||
void WakeupWaitingInterrupt();
|
||||
|
||||
private:
|
||||
void InitSynchronousInterrupt();
|
||||
std::shared_ptr<DigitalSource> m_source;
|
||||
hal::Handle<HAL_InterruptHandle> m_handle;
|
||||
};
|
||||
} // namespace frc
|
||||
Reference in New Issue
Block a user