mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[wpilib] Remove InterruptableSensorBase and replace with interrupt classes (#2410)
This commit is contained in:
@@ -42,16 +42,12 @@ struct Interrupt {
|
||||
HAL_Handle portHandle;
|
||||
uint8_t index;
|
||||
HAL_AnalogTriggerType trigType;
|
||||
bool watcher;
|
||||
int64_t risingTimestamp;
|
||||
int64_t fallingTimestamp;
|
||||
bool previousState;
|
||||
bool fireOnUp;
|
||||
bool fireOnDown;
|
||||
int32_t callbackId;
|
||||
|
||||
void* callbackParam;
|
||||
HAL_InterruptHandlerFunction callbackFunction;
|
||||
};
|
||||
|
||||
struct SynchronousWaitData {
|
||||
@@ -83,8 +79,7 @@ void InitializeInterrupts() {
|
||||
} // namespace hal::init
|
||||
|
||||
extern "C" {
|
||||
HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher,
|
||||
int32_t* status) {
|
||||
HAL_InterruptHandle HAL_InitializeInterrupts(int32_t* status) {
|
||||
hal::init::CheckInit();
|
||||
HAL_InterruptHandle handle = interruptHandles->Allocate();
|
||||
if (handle == HAL_kInvalidHandle) {
|
||||
@@ -100,19 +95,10 @@ HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher,
|
||||
anInterrupt->index = getHandleIndex(handle);
|
||||
anInterrupt->callbackId = -1;
|
||||
|
||||
anInterrupt->watcher = watcher;
|
||||
|
||||
return handle;
|
||||
}
|
||||
void* HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle,
|
||||
int32_t* status) {
|
||||
HAL_DisableInterrupts(interruptHandle, status);
|
||||
auto anInterrupt = interruptHandles->Get(interruptHandle);
|
||||
void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle) {
|
||||
interruptHandles->Free(interruptHandle);
|
||||
if (anInterrupt == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return anInterrupt->callbackParam;
|
||||
}
|
||||
|
||||
static void ProcessInterruptDigitalSynchronous(const char* name, void* param,
|
||||
@@ -352,12 +338,6 @@ int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle,
|
||||
return WaitResult::Timeout;
|
||||
}
|
||||
|
||||
// Check to make sure we are actually an interrupt in synchronous mode
|
||||
if (!interrupt->watcher) {
|
||||
*status = NiFpga_Status_InvalidParameter;
|
||||
return WaitResult::Timeout;
|
||||
}
|
||||
|
||||
if (interrupt->isAnalog) {
|
||||
return WaitForInterruptAnalog(interruptHandle, interrupt.get(), timeout,
|
||||
ignorePrevious);
|
||||
@@ -367,196 +347,6 @@ int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle,
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessInterruptDigitalAsynchronous(const char* name, void* param,
|
||||
const struct HAL_Value* value) {
|
||||
// void* is a HAL handle
|
||||
// convert to uintptr_t first, then to handle
|
||||
uintptr_t handleTmp = reinterpret_cast<uintptr_t>(param);
|
||||
HAL_InterruptHandle handle = static_cast<HAL_InterruptHandle>(handleTmp);
|
||||
auto interrupt = interruptHandles->Get(handle);
|
||||
if (interrupt == nullptr) {
|
||||
return;
|
||||
}
|
||||
// Have a valid interrupt
|
||||
if (value->type != HAL_Type::HAL_BOOLEAN) {
|
||||
return;
|
||||
}
|
||||
bool retVal = value->data.v_boolean;
|
||||
// If no change in interrupt, return;
|
||||
if (retVal == interrupt->previousState) {
|
||||
return;
|
||||
}
|
||||
int32_t mask = 0;
|
||||
if (interrupt->previousState) {
|
||||
interrupt->previousState = retVal;
|
||||
interrupt->fallingTimestamp = hal::GetFPGATime();
|
||||
mask = 1 << (8 + interrupt->index);
|
||||
if (!interrupt->fireOnDown) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
interrupt->previousState = retVal;
|
||||
interrupt->risingTimestamp = hal::GetFPGATime();
|
||||
mask = 1 << (interrupt->index);
|
||||
if (!interrupt->fireOnUp) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// run callback
|
||||
auto callback = interrupt->callbackFunction;
|
||||
if (callback == nullptr) {
|
||||
return;
|
||||
}
|
||||
callback(mask, interrupt->callbackParam);
|
||||
}
|
||||
|
||||
static void ProcessInterruptAnalogAsynchronous(const char* name, void* param,
|
||||
const struct HAL_Value* value) {
|
||||
// void* is a HAL handle
|
||||
// convert to intptr_t first, then to handle
|
||||
uintptr_t handleTmp = reinterpret_cast<uintptr_t>(param);
|
||||
HAL_InterruptHandle handle = static_cast<HAL_InterruptHandle>(handleTmp);
|
||||
auto interrupt = interruptHandles->Get(handle);
|
||||
if (interrupt == nullptr) {
|
||||
return;
|
||||
}
|
||||
// Have a valid interrupt
|
||||
if (value->type != HAL_Type::HAL_DOUBLE) {
|
||||
return;
|
||||
}
|
||||
int32_t status = 0;
|
||||
bool retVal = GetAnalogTriggerValue(interrupt->portHandle,
|
||||
interrupt->trigType, &status);
|
||||
if (status != 0) {
|
||||
return;
|
||||
}
|
||||
// If no change in interrupt, return;
|
||||
if (retVal == interrupt->previousState) {
|
||||
return;
|
||||
}
|
||||
int mask = 0;
|
||||
if (interrupt->previousState) {
|
||||
interrupt->previousState = retVal;
|
||||
interrupt->fallingTimestamp = hal::GetFPGATime();
|
||||
if (!interrupt->fireOnDown) {
|
||||
return;
|
||||
}
|
||||
mask = 1 << (8 + interrupt->index);
|
||||
} else {
|
||||
interrupt->previousState = retVal;
|
||||
interrupt->risingTimestamp = hal::GetFPGATime();
|
||||
if (!interrupt->fireOnUp) {
|
||||
return;
|
||||
}
|
||||
mask = 1 << (interrupt->index);
|
||||
}
|
||||
|
||||
// run callback
|
||||
auto callback = interrupt->callbackFunction;
|
||||
if (callback == nullptr) {
|
||||
return;
|
||||
}
|
||||
callback(mask, interrupt->callbackParam);
|
||||
}
|
||||
|
||||
static void EnableInterruptsDigital(HAL_InterruptHandle handle,
|
||||
Interrupt* interrupt) {
|
||||
int32_t status = 0;
|
||||
int32_t digitalIndex = GetDigitalInputChannel(interrupt->portHandle, &status);
|
||||
if (status != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
interrupt->previousState = SimDIOData[digitalIndex].value;
|
||||
|
||||
int32_t uid = SimDIOData[digitalIndex].value.RegisterCallback(
|
||||
&ProcessInterruptDigitalAsynchronous,
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(handle)), false);
|
||||
interrupt->callbackId = uid;
|
||||
}
|
||||
|
||||
static void EnableInterruptsAnalog(HAL_InterruptHandle handle,
|
||||
Interrupt* interrupt) {
|
||||
int32_t status = 0;
|
||||
int32_t analogIndex =
|
||||
GetAnalogTriggerInputIndex(interrupt->portHandle, &status);
|
||||
if (status != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
interrupt->previousState = GetAnalogTriggerValue(
|
||||
interrupt->portHandle, interrupt->trigType, &status);
|
||||
if (status != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t uid = SimAnalogInData[analogIndex].voltage.RegisterCallback(
|
||||
&ProcessInterruptAnalogAsynchronous,
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(handle)), false);
|
||||
interrupt->callbackId = uid;
|
||||
}
|
||||
|
||||
void HAL_EnableInterrupts(HAL_InterruptHandle interruptHandle,
|
||||
int32_t* status) {
|
||||
auto interrupt = interruptHandles->Get(interruptHandle);
|
||||
if (interrupt == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have not had a callback set, error out
|
||||
if (interrupt->callbackFunction == nullptr) {
|
||||
*status = INCOMPATIBLE_STATE;
|
||||
return;
|
||||
}
|
||||
|
||||
// EnableInterrupts has already been called
|
||||
if (interrupt->callbackId >= 0) {
|
||||
// We can double enable safely.
|
||||
return;
|
||||
}
|
||||
|
||||
if (interrupt->isAnalog) {
|
||||
EnableInterruptsAnalog(interruptHandle, interrupt.get());
|
||||
} else {
|
||||
EnableInterruptsDigital(interruptHandle, interrupt.get());
|
||||
}
|
||||
}
|
||||
void HAL_DisableInterrupts(HAL_InterruptHandle interruptHandle,
|
||||
int32_t* status) {
|
||||
auto interrupt = interruptHandles->Get(interruptHandle);
|
||||
if (interrupt == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to disable if we are already disabled
|
||||
if (interrupt->callbackId < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (interrupt->isAnalog) {
|
||||
// Do analog
|
||||
int32_t status = 0;
|
||||
int32_t analogIndex =
|
||||
GetAnalogTriggerInputIndex(interrupt->portHandle, &status);
|
||||
if (status != 0) {
|
||||
return;
|
||||
}
|
||||
SimAnalogInData[analogIndex].voltage.CancelCallback(interrupt->callbackId);
|
||||
} else {
|
||||
int32_t status = 0;
|
||||
int32_t digitalIndex =
|
||||
GetDigitalInputChannel(interrupt->portHandle, &status);
|
||||
if (status != 0) {
|
||||
return;
|
||||
}
|
||||
SimDIOData[digitalIndex].value.CancelCallback(interrupt->callbackId);
|
||||
}
|
||||
interrupt->callbackId = -1;
|
||||
}
|
||||
int64_t HAL_ReadInterruptRisingTimestamp(HAL_InterruptHandle interruptHandle,
|
||||
int32_t* status) {
|
||||
auto interrupt = interruptHandles->Get(interruptHandle);
|
||||
@@ -602,24 +392,6 @@ void HAL_RequestInterrupts(HAL_InterruptHandle interruptHandle,
|
||||
interrupt->trigType = analogTriggerType;
|
||||
interrupt->portHandle = digitalSourceHandle;
|
||||
}
|
||||
void HAL_AttachInterruptHandler(HAL_InterruptHandle interruptHandle,
|
||||
HAL_InterruptHandlerFunction handler,
|
||||
void* param, int32_t* status) {
|
||||
auto interrupt = interruptHandles->Get(interruptHandle);
|
||||
if (interrupt == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
interrupt->callbackFunction = handler;
|
||||
interrupt->callbackParam = param;
|
||||
}
|
||||
|
||||
void HAL_AttachInterruptHandlerThreaded(HAL_InterruptHandle interruptHandle,
|
||||
HAL_InterruptHandlerFunction handler,
|
||||
void* param, int32_t* status) {
|
||||
HAL_AttachInterruptHandler(interruptHandle, handler, param, status);
|
||||
}
|
||||
|
||||
void HAL_SetInterruptUpSourceEdge(HAL_InterruptHandle interruptHandle,
|
||||
HAL_Bool risingEdge, HAL_Bool fallingEdge,
|
||||
@@ -636,6 +408,19 @@ void HAL_SetInterruptUpSourceEdge(HAL_InterruptHandle interruptHandle,
|
||||
|
||||
void HAL_ReleaseWaitingInterrupt(HAL_InterruptHandle interruptHandle,
|
||||
int32_t* status) {
|
||||
// Requires a fairly large rewrite to get working
|
||||
auto interrupt = interruptHandles->Get(interruptHandle);
|
||||
if (interrupt == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
synchronousInterruptHandles->ForEach(
|
||||
[interruptHandle](SynchronousWaitDataHandle handle,
|
||||
SynchronousWaitData* data) {
|
||||
if (data->interruptHandle == interruptHandle) {
|
||||
data->waitPredicate = true;
|
||||
data->waitCond.notify_all();
|
||||
}
|
||||
});
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
Reference in New Issue
Block a user