[hal,wpilib] Move Alert to HAL (#8646)

SystemCore implementation is not yet connected to MRCComm.
This commit is contained in:
Peter Johnson
2026-03-03 21:58:47 -07:00
committed by GitHub
parent f4935a2ea9
commit 733cfa4b07
33 changed files with 1719 additions and 1121 deletions

View File

@@ -0,0 +1,155 @@
// 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.
#include "wpi/hal/Alert.h"
#include <atomic>
#include <cstring>
#include <memory>
#include <string>
#include "HALInitializer.h"
#include "wpi/hal/Errors.h"
#include "wpi/hal/HALBase.h"
#include "wpi/hal/Types.h"
#include "wpi/hal/handles/UnlimitedHandleResource.h"
#include "wpi/hal/simulation/AlertData.h"
#include "wpi/util/mutex.hpp"
#include "wpi/util/string.h"
namespace {
struct Alert {
Alert(std::string_view group, std::string_view text, int32_t level)
: group{group}, text{text}, level{level} {}
wpi::util::mutex textMutex;
std::string group;
std::string text;
std::atomic<int64_t> activeStartTime{0}; // non-zero when active
int32_t level = 0;
};
} // namespace
using namespace wpi::hal;
static UnlimitedHandleResource<HAL_AlertHandle, Alert, HAL_HandleEnum::Alert>*
alertHandles;
namespace wpi::hal::init {
void InitializeAlert() {
static UnlimitedHandleResource<HAL_AlertHandle, Alert, HAL_HandleEnum::Alert>
aH;
alertHandles = &aH;
}
} // namespace wpi::hal::init
extern "C" {
HAL_AlertHandle HAL_CreateAlert(const WPI_String* group, const WPI_String* text,
int32_t level, int32_t* status) {
wpi::hal::init::CheckInit();
std::shared_ptr<Alert> alert = std::make_shared<Alert>(
wpi::util::to_string_view(group), wpi::util::to_string_view(text), level);
HAL_AlertHandle handle = alertHandles->Allocate(alert);
if (handle == HAL_kInvalidHandle) {
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
}
return handle;
}
void HAL_DestroyAlert(HAL_AlertHandle alertHandle) {
alertHandles->Free(alertHandle);
}
void HAL_SetAlertActive(HAL_AlertHandle alertHandle, HAL_Bool active,
int32_t* status) {
auto alert = alertHandles->Get(alertHandle);
if (!alert) {
*status = HAL_HANDLE_ERROR;
return;
}
if (active) {
if (alert->activeStartTime.load(std::memory_order_relaxed) != 0) {
// Already active, do nothing (avoids cost of getting time)
return;
}
int64_t now = HAL_GetFPGATime(status);
int64_t expected = 0;
// use compare-exchange to avoid potential race
alert->activeStartTime.compare_exchange_strong(expected, now);
} else {
alert->activeStartTime = 0;
}
}
HAL_Bool HAL_IsAlertActive(HAL_AlertHandle alertHandle, int32_t* status) {
auto alert = alertHandles->Get(alertHandle);
if (!alert) {
*status = HAL_HANDLE_ERROR;
return false;
}
return alert->activeStartTime != 0;
}
void HAL_SetAlertText(HAL_AlertHandle alertHandle, const WPI_String* text,
int32_t* status) {
auto alert = alertHandles->Get(alertHandle);
if (!alert) {
*status = HAL_HANDLE_ERROR;
return;
}
std::scoped_lock lock(alert->textMutex);
alert->text = wpi::util::to_string_view(text);
}
void HAL_GetAlertText(HAL_AlertHandle alertHandle, struct WPI_String* text,
int32_t* status) {
auto alert = alertHandles->Get(alertHandle);
if (alert) {
std::scoped_lock lock(alert->textMutex);
*text = wpi::util::alloc_wpi_string(alert->text);
} else {
*status = HAL_HANDLE_ERROR;
*text = WPI_String{};
}
}
int32_t HALSIM_GetNumAlerts(void) {
int32_t count = 0;
alertHandles->ForEach([&](auto, auto) { ++count; });
return count;
}
int32_t HALSIM_GetAlerts(struct HALSIM_AlertInfo* arr, int32_t length) {
int32_t num = 0;
alertHandles->ForEach([&](HAL_AlertHandle handle, Alert* alert) {
if (num < length) {
arr[num].handle = handle;
arr[num].group = wpi::util::alloc_wpi_string(alert->group);
{
std::scoped_lock lock(alert->textMutex);
arr[num].text = wpi::util::alloc_wpi_string(alert->text);
}
arr[num].activeStartTime =
alert->activeStartTime.load(std::memory_order_relaxed);
arr[num].level = alert->level;
}
++num;
});
return num;
}
void HALSIM_FreeAlerts(struct HALSIM_AlertInfo* arr, int32_t length) {
for (int32_t i = 0; i < length; ++i) {
WPI_FreeString(&arr[i].group);
WPI_FreeString(&arr[i].text);
}
}
void HALSIM_ResetAlertData(void) {
alertHandles->ResetHandles();
}
} // extern "C"

View File

@@ -82,6 +82,7 @@ void InitializeHAL() {
InitializeRoboRioData();
InitializeSimDeviceData();
InitializeAddressableLED();
InitializeAlert();
InitializeAnalogInput();
InitializeAnalogInternal();
InitializeCAN();

View File

@@ -34,6 +34,7 @@ extern void InitializePWMData();
extern void InitializeRoboRioData();
extern void InitializeSimDeviceData();
extern void InitializeAddressableLED();
extern void InitializeAlert();
extern void InitializeAnalogInput();
extern void InitializeAnalogInternal();
extern void InitializeCAN();

View File

@@ -4,6 +4,7 @@
#include "../PortsInternal.h"
#include "wpi/hal/simulation/AddressableLEDData.h"
#include "wpi/hal/simulation/AlertData.h"
#include "wpi/hal/simulation/AnalogInData.h"
#include "wpi/hal/simulation/CTREPCMData.h"
#include "wpi/hal/simulation/CanData.h"
@@ -70,4 +71,5 @@ extern "C" void HALSIM_ResetAllSimData(void) {
HALSIM_ResetRoboRioData();
HALSIM_ResetSimDeviceData();
HALSIM_ResetAlertData();
}