[hal, wpilib] Update Addressable LED support (#8100)

This commit is contained in:
Peter Johnson
2025-07-21 21:52:10 -07:00
committed by GitHub
parent 8aa312fb6f
commit f3af50fc8e
40 changed files with 857 additions and 1104 deletions

View File

@@ -13,7 +13,7 @@
using namespace hal;
using namespace wpi::java;
static_assert(sizeof(jbyte) * 4 == sizeof(HAL_AddressableLEDData));
static_assert(sizeof(jbyte) * 3 == sizeof(HAL_AddressableLEDData));
static_assert(edu_wpi_first_hal_AddressableLEDJNI_COLOR_ORDER_RGB ==
HAL_ALED_RGB);
@@ -36,12 +36,12 @@ extern "C" {
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_AddressableLEDJNI_initialize
(JNIEnv* env, jclass, jint handle)
(JNIEnv* env, jclass, jint channel)
{
int32_t status = 0;
auto ret = HAL_InitializeAddressableLED(
static_cast<HAL_DigitalHandle>(handle), &status);
CheckStatus(env, status);
auto stack = wpi::java::GetJavaStackTrace(env, "edu.wpi.first");
auto ret = HAL_InitializeAddressableLED(channel, stack.c_str(), &status);
CheckStatusForceThrow(env, status);
return ret;
}
@@ -61,17 +61,16 @@ Java_edu_wpi_first_hal_AddressableLEDJNI_free
/*
* Class: edu_wpi_first_hal_AddressableLEDJNI
* Method: setColorOrder
* Method: setStart
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AddressableLEDJNI_setColorOrder
(JNIEnv* env, jclass, jint handle, jint colorOrder)
Java_edu_wpi_first_hal_AddressableLEDJNI_setStart
(JNIEnv* env, jclass, jint handle, jint start)
{
int32_t status = 0;
HAL_SetAddressableLEDColorOrder(
static_cast<HAL_AddressableLEDHandle>(handle),
static_cast<HAL_AddressableLEDColorOrder>(colorOrder), &status);
HAL_SetAddressableLEDStart(static_cast<HAL_AddressableLEDHandle>(handle),
start, &status);
CheckStatus(env, status);
}
@@ -93,80 +92,79 @@ Java_edu_wpi_first_hal_AddressableLEDJNI_setLength
/*
* Class: edu_wpi_first_hal_AddressableLEDJNI
* Method: setData
* Signature: (I[B)V
* Signature: (II[BII)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AddressableLEDJNI_setData
(JNIEnv* env, jclass, jint handle, jbyteArray arr)
(JNIEnv* env, jclass, jint outStart, jint colorOrder, jbyteArray data,
jint start, jint len)
{
if (!data) {
ThrowNullPointerException(env, "data is null");
return;
}
if (start < 0) {
ThrowIndexOutOfBoundsException(env, "start must be >= 0");
return;
}
if (len < 0) {
ThrowIndexOutOfBoundsException(env, "len must be >= 0");
return;
}
JSpan<const jbyte> cdata{env, data};
if (static_cast<unsigned int>(start + len) > cdata.size()) {
ThrowIndexOutOfBoundsException(
env, "start + len must be smaller than array length");
return;
}
if ((len % 3) != 0) {
ThrowIndexOutOfBoundsException(env, "len must be a multiple of 3");
return;
}
auto rawdata = cdata.uarray().subspan(start, len);
int32_t status = 0;
JSpan<const jbyte> jArrRef{env, arr};
HAL_WriteAddressableLEDData(
static_cast<HAL_AddressableLEDHandle>(handle),
reinterpret_cast<const HAL_AddressableLEDData*>(jArrRef.data()),
jArrRef.size() / 4, &status);
CheckStatus(env, status);
HAL_SetAddressableLEDData(
outStart, rawdata.size() / 3,
static_cast<HAL_AddressableLEDColorOrder>(colorOrder),
reinterpret_cast<const HAL_AddressableLEDData*>(rawdata.data()), &status);
}
/*
* Class: edu_wpi_first_hal_AddressableLEDJNI
* Method: setBitTiming
* Signature: (IIIII)V
* Method: setDataFromBuffer
* Signature: (IILjava/lang/Object;II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AddressableLEDJNI_setBitTiming
(JNIEnv* env, jclass, jint handle, jint highTime0, jint lowTime0,
jint highTime1, jint lowTime1)
Java_edu_wpi_first_hal_AddressableLEDJNI_setDataFromBuffer
(JNIEnv* env, jclass, jint outStart, jint colorOrder, jobject data,
jint start, jint len)
{
if (!data) {
ThrowNullPointerException(env, "data is null");
return;
}
if (start < 0) {
ThrowIndexOutOfBoundsException(env, "start must be >= 0");
return;
}
if (len < 0) {
ThrowIndexOutOfBoundsException(env, "len must be >= 0");
return;
}
JSpan<const jbyte> cdata{env, data, static_cast<size_t>(start + len)};
if (!cdata) {
ThrowIllegalArgumentException(env, "data must be a native ByteBuffer");
return;
}
if ((len % 3) != 0) {
ThrowIndexOutOfBoundsException(env, "len must be a multiple of 3");
return;
}
auto rawdata = cdata.uarray().subspan(start, len);
int32_t status = 0;
HAL_SetAddressableLEDBitTiming(static_cast<HAL_AddressableLEDHandle>(handle),
highTime0, lowTime0, highTime1, lowTime1,
&status);
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_hal_AddressableLEDJNI
* Method: setSyncTime
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AddressableLEDJNI_setSyncTime
(JNIEnv* env, jclass, jint handle, jint syncTime)
{
int32_t status = 0;
HAL_SetAddressableLEDSyncTime(static_cast<HAL_AddressableLEDHandle>(handle),
syncTime, &status);
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_hal_AddressableLEDJNI
* Method: start
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AddressableLEDJNI_start
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
HAL_StartAddressableLEDOutput(static_cast<HAL_AddressableLEDHandle>(handle),
&status);
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_hal_AddressableLEDJNI
* Method: stop
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AddressableLEDJNI_stop
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
HAL_StopAddressableLEDOutput(static_cast<HAL_AddressableLEDHandle>(handle),
&status);
CheckStatus(env, status);
HAL_SetAddressableLEDData(
outStart, rawdata.size() / 3,
static_cast<HAL_AddressableLEDColorOrder>(colorOrder),
reinterpret_cast<const HAL_AddressableLEDData*>(rawdata.data()), &status);
}
} // extern "C"

View File

@@ -40,6 +40,7 @@ static_assert(edu_wpi_first_hal_HALUtil_RUNTIME_SYSTEMCORE ==
static JavaVM* jvm = nullptr;
static JException illegalArgExCls;
static JException indexOobExCls;
static JException boundaryExCls;
static JException allocationExCls;
static JException halHandleExCls;
@@ -68,6 +69,7 @@ static const JClassInit classes[] = {
static const JExceptionInit exceptions[] = {
{"java/lang/IllegalArgumentException", &illegalArgExCls},
{"java/lang/IndexOutOfBoundsException", &indexOobExCls},
{"edu/wpi/first/hal/util/BoundaryException", &boundaryExCls},
{"edu/wpi/first/hal/util/AllocationException", &allocationExCls},
{"edu/wpi/first/hal/util/HalHandleException", &halHandleExCls},
@@ -159,6 +161,10 @@ void ThrowIllegalArgumentException(JNIEnv* env, std::string_view msg) {
illegalArgExCls.Throw(env, msg);
}
void ThrowIndexOutOfBoundsException(JNIEnv* env, std::string_view msg) {
indexOobExCls.Throw(env, msg);
}
void ThrowBoundaryException(JNIEnv* env, double value, double lower,
double upper) {
static jmethodID getMessage = nullptr;

View File

@@ -46,6 +46,7 @@ void ThrowNullPointerException(JNIEnv* env, std::string_view msg);
void ThrowCANStreamOverflowException(JNIEnv* env, jobjectArray messages,
jint length);
void ThrowIllegalArgumentException(JNIEnv* env, std::string_view msg);
void ThrowIndexOutOfBoundsException(JNIEnv* env, std::string_view msg);
void ThrowBoundaryException(JNIEnv* env, double value, double lower,
double upper);

View File

@@ -11,7 +11,7 @@
#include "edu_wpi_first_hal_simulation_AddressableLEDDataJNI.h"
#include "hal/simulation/AddressableLEDData.h"
static_assert(sizeof(jbyte) * 4 == sizeof(HAL_AddressableLEDData));
static_assert(sizeof(jbyte) * 3 == sizeof(HAL_AddressableLEDData));
using namespace hal;
using namespace wpi::java;
@@ -71,53 +71,52 @@ Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_setInitialized
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: registerOutputPortCallback
* Method: registerStartCallback
* Signature: (ILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_registerOutputPortCallback
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_registerStartCallback
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
{
return sim::AllocateCallback(
env, index, callback, initialNotify,
&HALSIM_RegisterAddressableLEDOutputPortCallback);
return sim::AllocateCallback(env, index, callback, initialNotify,
&HALSIM_RegisterAddressableLEDStartCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: cancelOutputPortCallback
* Method: cancelStartCallback
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_cancelOutputPortCallback
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_cancelStartCallback
(JNIEnv* env, jclass, jint index, jint handle)
{
return sim::FreeCallback(env, handle, index,
&HALSIM_CancelAddressableLEDOutputPortCallback);
&HALSIM_CancelAddressableLEDStartCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: getOutputPort
* Method: getStart
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_getOutputPort
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_getStart
(JNIEnv*, jclass, jint index)
{
return HALSIM_GetAddressableLEDOutputPort(index);
return HALSIM_GetAddressableLEDStart(index);
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: setOutputPort
* Method: setStart
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_setOutputPort
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_setStart
(JNIEnv*, jclass, jint index, jint value)
{
HALSIM_SetAddressableLEDOutputPort(index, value);
HALSIM_SetAddressableLEDStart(index, value);
}
/*
@@ -170,96 +169,50 @@ Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_setLength
HALSIM_SetAddressableLEDLength(index, value);
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: registerRunningCallback
* Signature: (ILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_registerRunningCallback
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
{
return sim::AllocateCallback(env, index, callback, initialNotify,
&HALSIM_RegisterAddressableLEDRunningCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: cancelRunningCallback
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_cancelRunningCallback
(JNIEnv* env, jclass, jint index, jint handle)
{
return sim::FreeCallback(env, handle, index,
&HALSIM_CancelAddressableLEDRunningCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: getRunning
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_getRunning
(JNIEnv*, jclass, jint index)
{
return HALSIM_GetAddressableLEDRunning(index);
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: setRunning
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_setRunning
(JNIEnv*, jclass, jint index, jboolean value)
{
HALSIM_SetAddressableLEDRunning(index, value);
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: registerDataCallback
* Signature: (ILjava/lang/Object;)I
* Signature: (Ljava/lang/Object;)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_registerDataCallback
(JNIEnv* env, jclass, jint index, jobject callback)
(JNIEnv* env, jclass, jobject callback)
{
return sim::AllocateConstBufferCallback(
env, index, callback, &HALSIM_RegisterAddressableLEDDataCallback);
env, -1, callback,
[](int32_t, HAL_ConstBufferCallback callback, void* param) {
return HALSIM_RegisterAddressableLEDDataCallback(callback, param);
});
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: cancelDataCallback
* Signature: (II)V
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_cancelDataCallback
(JNIEnv* env, jclass, jint index, jint handle)
(JNIEnv* env, jclass, jint handle)
{
sim::FreeConstBufferCallback(env, handle, index,
&HALSIM_CancelAddressableLEDDataCallback);
sim::FreeConstBufferCallback(env, handle, -1, [](int32_t, int32_t uid) {
HALSIM_CancelAddressableLEDDataCallback(uid);
});
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: getData
* Signature: (I)[B
* Signature: (II)[B
*/
JNIEXPORT jbyteArray JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_getData
(JNIEnv* env, jclass, jint index)
(JNIEnv* env, jclass, jint start, jint length)
{
auto data =
std::make_unique<HAL_AddressableLEDData[]>(HAL_kAddressableLEDMaxLength);
int32_t length = HALSIM_GetAddressableLEDData(index, data.get());
length = HALSIM_GetAddressableLEDData(start, length, data.get());
return MakeJByteArray(
env, std::span(reinterpret_cast<jbyte*>(data.get()), length * 4));
env, std::span(reinterpret_cast<jbyte*>(data.get()), length * 3));
}
/*
@@ -269,13 +222,13 @@ Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_getData
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_setData
(JNIEnv* env, jclass, jint index, jbyteArray arr)
(JNIEnv* env, jclass, jint start, jbyteArray arr)
{
JSpan<const jbyte> jArrRef{env, arr};
auto arrRef = jArrRef.array();
HALSIM_SetAddressableLEDData(
index, reinterpret_cast<const HAL_AddressableLEDData*>(arrRef.data()),
arrRef.size() / 4);
start, arrRef.size() / 3,
reinterpret_cast<const HAL_AddressableLEDData*>(arrRef.data()));
}
/*
@@ -290,16 +243,4 @@ Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_resetData
HALSIM_ResetAddressableLEDData(index);
}
/*
* Class: edu_wpi_first_hal_simulation_AddressableLEDDataJNI
* Method: findForChannel
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_findForChannel
(JNIEnv*, jclass, jint channel)
{
return HALSIM_FindAddressableLEDForChannel(channel);
}
} // extern "C"

View File

@@ -20,14 +20,16 @@ extern "C" {
#endif
/**
* Initialize Addressable LED using a PWM Digital handle.
* Creates a new instance of an addressable LED.
*
* @param[in] outputPort handle of the digital port for PWM
* @param[in] channel the smartio channel
* @param[in] allocationLocation the location where the allocation is occurring
* (can be null)
* @param[out] status the error code, or 0 for success
* @return Addressable LED handle
*/
HAL_AddressableLEDHandle HAL_InitializeAddressableLED(
HAL_DigitalHandle outputPort, int32_t* status);
int32_t channel, const char* allocationLocation, int32_t* status);
/**
* Free the Addressable LED Handle.
@@ -37,34 +39,26 @@ HAL_AddressableLEDHandle HAL_InitializeAddressableLED(
void HAL_FreeAddressableLED(HAL_AddressableLEDHandle handle);
/**
* Sets the color order for the addressable LED output. The default order is
* GRB. This will take effect on the next call to HAL_WriteAddressableLEDData().
* @param[in] handle the Addressable LED handle
* @param[in] colorOrder the color order
* @param[out] status the error code, or 0 for success
*/
void HAL_SetAddressableLEDColorOrder(HAL_AddressableLEDHandle handle,
HAL_AddressableLEDColorOrder colorOrder,
int32_t* status);
/**
* Set the Addressable LED PWM Digital port.
* Sets the start buffer location used for the LED strip.
*
* <p>All addressable LEDs use a single backing buffer 1024 LEDs in size.
* The max length for a single output is 1024 LEDs (with an offset of zero).
*
* @param[in] handle the Addressable LED handle
* @param[in] outputPort The digital handle of the PWM port
* @param[in] start the strip start, in LEDs
* @param[out] status the error code, or 0 for success
*/
void HAL_SetAddressableLEDOutputPort(HAL_AddressableLEDHandle handle,
HAL_DigitalHandle outputPort,
int32_t* status);
void HAL_SetAddressableLEDStart(HAL_AddressableLEDHandle handle, int32_t start,
int32_t* status);
/**
* Sets the length of the LED strip.
*
* <p>The max length is 5460 LEDs.
* <p>All addressable LEDs use a single backing buffer 1024 LEDs in size.
* The max length for a single output is 1024 LEDs (with an offset of zero).
*
* @param[in] handle the Addressable LED handle
* @param[in] length the strip length
* @param[in] length the strip length, in LEDs
* @param[out] status the error code, or 0 for success
*/
void HAL_SetAddressableLEDLength(HAL_AddressableLEDHandle handle,
@@ -73,68 +67,19 @@ void HAL_SetAddressableLEDLength(HAL_AddressableLEDHandle handle,
/**
* Sets the led output data.
*
* <p>If the output is enabled, this will start writing the next data cycle.
* It is safe to call, even while output is enabled.
* <p>All addressable LEDs use a single backing buffer 1024 LEDs in size.
* This function may be used to set part of or all of the buffer.
*
* @param[in] handle the Addressable LED handle
* @param[in] start the strip start, in LEDs
* @param[in] length the strip length, in LEDs
* @param[in] colorOrder the color order
* @param[in] data the buffer to write
* @param[in] length the strip length
* @param[out] status the error code, or 0 for success
*/
void HAL_WriteAddressableLEDData(HAL_AddressableLEDHandle handle,
const struct HAL_AddressableLEDData* data,
int32_t length, int32_t* status);
/**
* Sets the bit timing.
*
* <p>By default, the driver is set up to drive WS2812B and WS2815, so nothing
* needs to be set for those.
*
* @param[in] handle the Addressable LED handle
* @param[in] highTime0 high time for 0 bit in nanoseconds (default 400 ns)
* @param[in] lowTime0 low time for 0 bit in nanoseconds (default 900 ns)
* @param[in] highTime1 high time for 1 bit in nanoseconds (default 900 ns)
* @param[in] lowTime1 low time for 1 bit in nanoseconds (default 600 ns)
* @param[out] status the error code, or 0 for success
*/
void HAL_SetAddressableLEDBitTiming(HAL_AddressableLEDHandle handle,
int32_t highTime0, int32_t lowTime0,
int32_t highTime1, int32_t lowTime1,
int32_t* status);
/**
* Sets the sync time.
*
* <p>The sync time is the time to hold output so LEDs enable. Default set for
* WS2812B and WS2815.
*
* @param[in] handle the Addressable LED handle
* @param[in] syncTime the sync time in microseconds (default 280 μs)
* @param[out] status the error code, or 0 for success
*/
void HAL_SetAddressableLEDSyncTime(HAL_AddressableLEDHandle handle,
int32_t syncTime, int32_t* status);
/**
* Starts the output.
*
* <p>The output writes continuously.
*
* @param[in] handle the Addressable LED handle
* @param[out] status the error code, or 0 for success
*/
void HAL_StartAddressableLEDOutput(HAL_AddressableLEDHandle handle,
int32_t* status);
/**
* Stops the output.
*
* @param[in] handle the Addressable LED handle
* @param[out] status the error code, or 0 for success
*/
void HAL_StopAddressableLEDOutput(HAL_AddressableLEDHandle handle,
int32_t* status);
void HAL_SetAddressableLEDData(int32_t start, int32_t length,
HAL_AddressableLEDColorOrder colorOrder,
const struct HAL_AddressableLEDData* data,
int32_t* status);
#ifdef __cplusplus
} // extern "C"

View File

@@ -7,15 +7,14 @@
#include <hal/Types.h>
#include <stdint.h>
/** max length of LED strip supported by FPGA. */
#define HAL_kAddressableLEDMaxLength 5460
/** max length of LED strip supported by device. */
#define HAL_kAddressableLEDMaxLength 1024
/** structure for holding one LED's color data. */
struct HAL_AddressableLEDData {
uint8_t b; ///< blue value
uint8_t g; ///< green value
uint8_t r; ///< red value
uint8_t padding;
};
/**

View File

@@ -12,8 +12,6 @@
extern "C" {
#endif
int32_t HALSIM_FindAddressableLEDForChannel(int32_t channel);
void HALSIM_ResetAddressableLEDData(int32_t index);
int32_t HALSIM_RegisterAddressableLEDInitializedCallback(
@@ -23,12 +21,13 @@ void HALSIM_CancelAddressableLEDInitializedCallback(int32_t index, int32_t uid);
HAL_Bool HALSIM_GetAddressableLEDInitialized(int32_t index);
void HALSIM_SetAddressableLEDInitialized(int32_t index, HAL_Bool initialized);
int32_t HALSIM_RegisterAddressableLEDOutputPortCallback(
int32_t index, HAL_NotifyCallback callback, void* param,
HAL_Bool initialNotify);
void HALSIM_CancelAddressableLEDOutputPortCallback(int32_t index, int32_t uid);
int32_t HALSIM_GetAddressableLEDOutputPort(int32_t index);
void HALSIM_SetAddressableLEDOutputPort(int32_t index, int32_t outputPort);
int32_t HALSIM_RegisterAddressableLEDStartCallback(int32_t index,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify);
void HALSIM_CancelAddressableLEDStartCallback(int32_t index, int32_t uid);
int32_t HALSIM_GetAddressableLEDStart(int32_t index);
void HALSIM_SetAddressableLEDStart(int32_t index, int32_t start);
int32_t HALSIM_RegisterAddressableLEDLengthCallback(int32_t index,
HAL_NotifyCallback callback,
@@ -38,21 +37,13 @@ void HALSIM_CancelAddressableLEDLengthCallback(int32_t index, int32_t uid);
int32_t HALSIM_GetAddressableLEDLength(int32_t index);
void HALSIM_SetAddressableLEDLength(int32_t index, int32_t length);
int32_t HALSIM_RegisterAddressableLEDRunningCallback(
int32_t index, HAL_NotifyCallback callback, void* param,
HAL_Bool initialNotify);
void HALSIM_CancelAddressableLEDRunningCallback(int32_t index, int32_t uid);
HAL_Bool HALSIM_GetAddressableLEDRunning(int32_t index);
void HALSIM_SetAddressableLEDRunning(int32_t index, HAL_Bool running);
int32_t HALSIM_RegisterAddressableLEDDataCallback(
int32_t index, HAL_ConstBufferCallback callback, void* param);
void HALSIM_CancelAddressableLEDDataCallback(int32_t index, int32_t uid);
int32_t HALSIM_GetAddressableLEDData(int32_t index,
HAL_ConstBufferCallback callback, void* param);
void HALSIM_CancelAddressableLEDDataCallback(int32_t uid);
int32_t HALSIM_GetAddressableLEDData(int32_t start, int32_t length,
struct HAL_AddressableLEDData* data);
void HALSIM_SetAddressableLEDData(int32_t index,
const struct HAL_AddressableLEDData* data,
int32_t length);
void HALSIM_SetAddressableLEDData(int32_t start, int32_t length,
const struct HAL_AddressableLEDData* data);
void HALSIM_RegisterAddressableLEDAllCallbacks(int32_t index,
HAL_NotifyCallback callback,

View File

@@ -12,108 +12,90 @@
#include "PortsInternal.h"
#include "hal/Errors.h"
#include "hal/handles/HandlesInternal.h"
#include "hal/handles/LimitedHandleResource.h"
#include "hal/handles/IndexedHandleResource.h"
#include "mockdata/AddressableLEDDataInternal.h"
using namespace hal;
namespace {
struct AddressableLED {
uint8_t index;
};
} // namespace
static LimitedHandleResource<HAL_AddressableLEDHandle, AddressableLED,
kNumAddressableLEDs,
HAL_HandleEnum::AddressableLED>* ledHandles;
namespace hal::init {
void InitializeAddressableLED() {
static LimitedHandleResource<HAL_AddressableLEDHandle, AddressableLED,
kNumAddressableLEDs,
HAL_HandleEnum::AddressableLED>
dcH;
ledHandles = &dcH;
}
void InitializeAddressableLED() {}
} // namespace hal::init
extern "C" {
HAL_AddressableLEDHandle HAL_InitializeAddressableLED(
HAL_DigitalHandle outputPort, int32_t* status) {
int32_t channel, const char* allocationLocation, int32_t* status) {
hal::init::CheckInit();
auto digitalPort =
hal::digitalChannelHandles->Get(outputPort, hal::HAL_HandleEnum::PWM);
if (channel < 0 || channel >= kNumAddressableLEDs) {
*status = RESOURCE_OUT_OF_RANGE;
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for AddressableLED",
0, kNumAddressableLEDs, channel);
return HAL_kInvalidHandle;
}
if (!digitalPort) {
// If DIO was passed, channel error, else generic error
if (getHandleType(outputPort) == hal::HAL_HandleEnum::DIO) {
*status = HAL_LED_CHANNEL_ERROR;
HAL_DigitalHandle handle;
auto port = digitalChannelHandles->Allocate(
channel, HAL_HandleEnum::AddressableLED, &handle, status);
if (*status != 0) {
if (port) {
hal::SetLastErrorPreviouslyAllocated(status, "PWM or DIO", channel,
port->previousAllocation);
} else {
*status = HAL_HANDLE_ERROR;
hal::SetLastErrorIndexOutOfRange(status,
"Invalid Index for AddressableLED", 0,
kNumAddressableLEDs, channel);
}
return HAL_kInvalidHandle;
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
}
if (digitalPort->channel >= kNumPWMHeaders) {
*status = HAL_LED_CHANNEL_ERROR;
return HAL_kInvalidHandle;
}
port->channel = static_cast<uint8_t>(channel);
HAL_AddressableLEDHandle handle = ledHandles->Allocate();
if (handle == HAL_kInvalidHandle) {
*status = NO_AVAILABLE_RESOURCES;
return HAL_kInvalidHandle;
}
SimAddressableLEDData[channel].start = 0;
SimAddressableLEDData[channel].length = 0;
SimAddressableLEDData[channel].initialized = true;
port->previousAllocation = allocationLocation ? allocationLocation : "";
auto led = ledHandles->Get(handle);
if (!led) { // would only occur on thread issue
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
}
int16_t index = getHandleIndex(handle);
SimAddressableLEDData[index].outputPort = digitalPort->channel;
SimAddressableLEDData[index].length = 1;
SimAddressableLEDData[index].running = false;
SimAddressableLEDData[index].initialized = true;
led->index = index;
return handle;
}
void HAL_FreeAddressableLED(HAL_AddressableLEDHandle handle) {
auto led = ledHandles->Get(handle);
ledHandles->Free(handle);
if (!led) {
auto port =
digitalChannelHandles->Get(handle, HAL_HandleEnum::AddressableLED);
// no status, so no need to check for a proper free.
digitalChannelHandles->Free(handle, HAL_HandleEnum::AddressableLED);
if (port == nullptr) {
return;
}
SimAddressableLEDData[led->index].running = false;
SimAddressableLEDData[led->index].initialized = false;
SimAddressableLEDData[port->channel].initialized = false;
}
void HAL_SetAddressableLEDColorOrder(HAL_AddressableLEDHandle handle,
HAL_AddressableLEDColorOrder colorOrder,
int32_t* status) {}
void HAL_SetAddressableLEDOutputPort(HAL_AddressableLEDHandle handle,
HAL_DigitalHandle outputPort,
int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
void HAL_SetAddressableLEDStart(HAL_AddressableLEDHandle handle, int32_t start,
int32_t* status) {
auto port =
digitalChannelHandles->Get(handle, HAL_HandleEnum::AddressableLED);
if (!port) {
*status = HAL_HANDLE_ERROR;
return;
}
if (auto port = digitalChannelHandles->Get(outputPort, HAL_HandleEnum::PWM)) {
SimAddressableLEDData[led->index].outputPort = port->channel;
} else {
SimAddressableLEDData[led->index].outputPort = -1;
if (start > HAL_kAddressableLEDMaxLength || start < 0) {
*status = PARAMETER_OUT_OF_RANGE;
hal::SetLastError(
status,
fmt::format(
"LED start must be less than or equal to {}. {} was requested",
HAL_kAddressableLEDMaxLength, start));
return;
}
SimAddressableLEDData[port->channel].start = start;
}
void HAL_SetAddressableLEDLength(HAL_AddressableLEDHandle handle,
int32_t length, int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
auto port =
digitalChannelHandles->Get(handle, HAL_HandleEnum::AddressableLED);
if (!port) {
*status = HAL_HANDLE_ERROR;
return;
}
@@ -126,54 +108,13 @@ void HAL_SetAddressableLEDLength(HAL_AddressableLEDHandle handle,
HAL_kAddressableLEDMaxLength, length));
return;
}
SimAddressableLEDData[led->index].length = length;
SimAddressableLEDData[port->channel].length = length;
}
void HAL_WriteAddressableLEDData(HAL_AddressableLEDHandle handle,
const struct HAL_AddressableLEDData* data,
int32_t length, int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
*status = HAL_HANDLE_ERROR;
return;
}
if (length > SimAddressableLEDData[led->index].length) {
*status = PARAMETER_OUT_OF_RANGE;
hal::SetLastError(
status,
fmt::format(
"Data length must be less than or equal to {}. {} was requested",
SimAddressableLEDData[led->index].length.Get(), length));
return;
}
SimAddressableLEDData[led->index].SetData(data, length);
}
void HAL_SetAddressableLEDBitTiming(HAL_AddressableLEDHandle handle,
int32_t highTime0, int32_t lowTime0,
int32_t highTime1, int32_t lowTime1,
int32_t* status) {}
void HAL_SetAddressableLEDSyncTime(HAL_AddressableLEDHandle handle,
int32_t syncTime, int32_t* status) {}
void HAL_StartAddressableLEDOutput(HAL_AddressableLEDHandle handle,
int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
*status = HAL_HANDLE_ERROR;
return;
}
SimAddressableLEDData[led->index].running = true;
}
void HAL_StopAddressableLEDOutput(HAL_AddressableLEDHandle handle,
int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
*status = HAL_HANDLE_ERROR;
return;
}
SimAddressableLEDData[led->index].running = false;
void HAL_SetAddressableLEDData(int32_t start, int32_t length,
HAL_AddressableLEDColorOrder colorOrder,
const struct HAL_AddressableLEDData* data,
int32_t* status) {
SimAddressableLEDDataBuffer->SetData(start, length, data);
}
} // extern "C"

View File

@@ -32,7 +32,7 @@ constexpr int32_t kNumREVPDHChannels = 24;
constexpr int32_t kNumPDSimModules = kNumREVPDHModules;
constexpr int32_t kNumPDSimChannels = kNumREVPDHChannels;
constexpr int32_t kNumDutyCycles = 6;
constexpr int32_t kNumAddressableLEDs = 1;
constexpr int32_t kNumAddressableLEDs = 6;
constexpr int32_t kNumREVPHModules = 63;
constexpr int32_t kNumREVPHChannels = 16;
constexpr int32_t kSPIAccelerometers = 5;

View File

@@ -14,62 +14,64 @@ namespace hal::init {
void InitializeAddressableLEDData() {
static AddressableLEDData sad[kNumAddressableLEDs];
::hal::SimAddressableLEDData = sad;
static AddressableLEDDataBuffer buf;
::hal::SimAddressableLEDDataBuffer = &buf;
}
} // namespace hal::init
AddressableLEDData* hal::SimAddressableLEDData;
AddressableLEDDataBuffer* hal::SimAddressableLEDDataBuffer;
void AddressableLEDData::ResetData() {
initialized.Reset(false);
outputPort.Reset(-1);
length.Reset(1);
running.Reset(false);
data.Reset();
start.Reset(0);
length.Reset(0);
}
void AddressableLEDData::SetData(const HAL_AddressableLEDData* d, int32_t len) {
len = (std::min)(HAL_kAddressableLEDMaxLength, len);
void AddressableLEDDataBuffer::SetData(int32_t start, int32_t len,
const HAL_AddressableLEDData* d) {
if ((start + len) > HAL_kAddressableLEDMaxLength) {
len = HAL_kAddressableLEDMaxLength - start;
}
if (len <= 0) {
return;
}
{
std::scoped_lock lock(m_dataMutex);
std::memcpy(m_data, d, len * sizeof(d[0]));
std::memcpy(&m_data[start], d, len * sizeof(d[0]));
}
data(reinterpret_cast<const uint8_t*>(d), len * sizeof(d[0]));
}
int32_t AddressableLEDData::GetData(HAL_AddressableLEDData* d) {
int32_t AddressableLEDDataBuffer::GetData(int32_t start, int32_t len,
HAL_AddressableLEDData* d) {
if ((start + len) > HAL_kAddressableLEDMaxLength) {
len = HAL_kAddressableLEDMaxLength - start;
}
if (len <= 0) {
return 0;
}
std::scoped_lock lock(m_dataMutex);
int32_t len = length;
if (d) {
std::memcpy(d, m_data, len * sizeof(d[0]));
std::memcpy(d, &m_data[start], len * sizeof(d[0]));
}
return len;
}
extern "C" {
int32_t HALSIM_FindAddressableLEDForChannel(int32_t channel) {
for (int i = 0; i < kNumAddressableLEDs; ++i) {
if (SimAddressableLEDData[i].initialized &&
SimAddressableLEDData[i].outputPort == channel) {
return i;
}
}
return -1;
}
void HALSIM_ResetAddressableLEDData(int32_t index) {
SimAddressableLEDData[index].ResetData();
}
int32_t HALSIM_GetAddressableLEDData(int32_t index,
int32_t HALSIM_GetAddressableLEDData(int32_t start, int32_t length,
struct HAL_AddressableLEDData* data) {
return SimAddressableLEDData[index].GetData(data);
return SimAddressableLEDDataBuffer->GetData(start, length, data);
}
void HALSIM_SetAddressableLEDData(int32_t index,
const struct HAL_AddressableLEDData* data,
int32_t length) {
SimAddressableLEDData[index].SetData(data, length);
void HALSIM_SetAddressableLEDData(int32_t start, int32_t length,
const struct HAL_AddressableLEDData* data) {
SimAddressableLEDDataBuffer->SetData(start, length, data);
}
#define DEFINE_CAPI(TYPE, CAPINAME, LOWERNAME) \
@@ -77,14 +79,14 @@ void HALSIM_SetAddressableLEDData(int32_t index,
SimAddressableLEDData, LOWERNAME)
DEFINE_CAPI(HAL_Bool, Initialized, initialized)
DEFINE_CAPI(int32_t, OutputPort, outputPort)
DEFINE_CAPI(int32_t, Start, start)
DEFINE_CAPI(int32_t, Length, length)
DEFINE_CAPI(HAL_Bool, Running, running)
#undef DEFINE_CAPI
#define DEFINE_CAPI(TYPE, CAPINAME, LOWERNAME) \
HAL_SIMCALLBACKREGISTRY_DEFINE_CAPI(TYPE, HALSIM, AddressableLED##CAPINAME, \
SimAddressableLEDData, LOWERNAME)
#define DEFINE_CAPI(TYPE, CAPINAME, LOWERNAME) \
HAL_SIMCALLBACKREGISTRY_DEFINE_CAPI_NOINDEX( \
TYPE, HALSIM, AddressableLED##CAPINAME, SimAddressableLEDDataBuffer, \
LOWERNAME)
DEFINE_CAPI(HAL_ConstBufferCallback, Data, data)
@@ -97,8 +99,7 @@ void HALSIM_RegisterAddressableLEDAllCallbacks(int32_t index,
void* param,
HAL_Bool initialNotify) {
REGISTER(initialized);
REGISTER(outputPort);
REGISTER(start);
REGISTER(length);
REGISTER(running);
}
} // extern "C"

View File

@@ -15,26 +15,29 @@
namespace hal {
class AddressableLEDData {
HAL_SIMDATAVALUE_DEFINE_NAME(Initialized)
HAL_SIMDATAVALUE_DEFINE_NAME(OutputPort)
HAL_SIMDATAVALUE_DEFINE_NAME(Start)
HAL_SIMDATAVALUE_DEFINE_NAME(Length)
HAL_SIMDATAVALUE_DEFINE_NAME(Running)
public:
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetInitializedName> initialized{
false};
SimDataValue<int32_t, HAL_MakeInt, GetStartName> start{0};
SimDataValue<int32_t, HAL_MakeInt, GetLengthName> length{0};
void ResetData();
};
extern AddressableLEDData* SimAddressableLEDData;
class AddressableLEDDataBuffer {
HAL_SIMDATAVALUE_DEFINE_NAME(Data)
wpi::recursive_spinlock m_dataMutex;
HAL_AddressableLEDData m_data[HAL_kAddressableLEDMaxLength];
public:
void SetData(const HAL_AddressableLEDData* d, int32_t len);
int32_t GetData(HAL_AddressableLEDData* d);
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetInitializedName> initialized{
false};
SimDataValue<int32_t, HAL_MakeInt, GetOutputPortName> outputPort{-1};
SimDataValue<int32_t, HAL_MakeInt, GetLengthName> length{1};
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetRunningName> running{false};
void SetData(int32_t start, int32_t len, const HAL_AddressableLEDData* d);
int32_t GetData(int32_t start, int32_t len, HAL_AddressableLEDData* d);
SimCallbackRegistry<HAL_ConstBufferCallback, GetDataName> data;
void ResetData();
};
extern AddressableLEDData* SimAddressableLEDData;
extern AddressableLEDDataBuffer* SimAddressableLEDDataBuffer;
} // namespace hal

View File

@@ -4,85 +4,152 @@
#include "hal/AddressableLED.h"
#include <stdint.h>
#include <cstdio>
#include <cstring>
#include <memory>
#include <thread>
#include <fmt/format.h>
#include <networktables/NetworkTableInstance.h>
#include <networktables/RawTopic.h>
#include "HALInitializer.h"
#include "HALInternal.h"
#include "PortsInternal.h"
#include "SmartIo.h"
#include "SystemServerInternal.h"
#include "hal/AddressableLEDTypes.h"
#include "hal/Errors.h"
#include "hal/cpp/fpga_clock.h"
using namespace hal;
#define LEDS_PREFIX "/leds/"
namespace {
constexpr const char* kRawKey = LEDS_PREFIX "raw";
struct AddressableLEDs {
explicit AddressableLEDs(nt::NetworkTableInstance inst)
: rawPub{inst.GetRawTopic(kRawKey).Publish(
"raw", {.periodic = 0.005, .sendAll = true})} {}
nt::RawPublisher rawPub;
uint8_t s_buffer[HAL_kAddressableLEDMaxLength * 3];
};
static AddressableLEDs* leds;
} // namespace
namespace hal::init {
void InitializeAddressableLED() {}
void InitializeAddressableLED() {
static AddressableLEDs leds_static{hal::GetSystemServer()};
leds = &leds_static;
}
} // namespace hal::init
extern "C" {
HAL_AddressableLEDHandle HAL_InitializeAddressableLED(
HAL_DigitalHandle outputPort, int32_t* status) {
int32_t channel, const char* allocationLocation, int32_t* status) {
hal::init::CheckInit();
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
if (channel < 0 || channel >= kNumSmartIo) {
*status = RESOURCE_OUT_OF_RANGE;
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for AddressableLED",
0, kNumSmartIo, channel);
return HAL_kInvalidHandle;
}
HAL_DigitalHandle handle;
auto port = smartIoHandles->Allocate(channel, HAL_HandleEnum::AddressableLED,
&handle, status);
if (*status != 0) {
if (port) {
hal::SetLastErrorPreviouslyAllocated(status, "SmartIo", channel,
port->previousAllocation);
} else {
hal::SetLastErrorIndexOutOfRange(
status, "Invalid Index for AddressableLED", 0, kNumSmartIo, channel);
}
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
}
port->channel = channel;
*status = port->InitializeMode(SmartIoMode::AddressableLED);
if (*status != 0) {
smartIoHandles->Free(handle, HAL_HandleEnum::AddressableLED);
return HAL_kInvalidHandle;
}
port->previousAllocation = allocationLocation ? allocationLocation : "";
return handle;
}
void HAL_FreeAddressableLED(HAL_AddressableLEDHandle handle) {}
void HAL_FreeAddressableLED(HAL_AddressableLEDHandle handle) {
auto port = smartIoHandles->Get(handle, HAL_HandleEnum::AddressableLED);
if (port == nullptr) {
return;
}
void HAL_SetAddressableLEDColorOrder(HAL_AddressableLEDHandle handle,
HAL_AddressableLEDColorOrder colorOrder,
int32_t* status) {
*status = HAL_HANDLE_ERROR;
return;
smartIoHandles->Free(handle, HAL_HandleEnum::AddressableLED);
// Wait for no other object to hold this handle.
auto start = hal::fpga_clock::now();
while (port.use_count() != 1) {
auto current = hal::fpga_clock::now();
if (start + std::chrono::seconds(1) < current) {
std::puts("AddressableLED handle free timeout");
std::fflush(stdout);
break;
}
std::this_thread::yield();
}
}
void HAL_SetAddressableLEDOutputPort(HAL_AddressableLEDHandle handle,
HAL_DigitalHandle outputPort,
int32_t* status) {
*status = HAL_HANDLE_ERROR;
return;
void HAL_SetAddressableLEDStart(HAL_AddressableLEDHandle handle, int32_t start,
int32_t* status) {
auto port = smartIoHandles->Get(handle, HAL_HandleEnum::AddressableLED);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
*status = port->SetLedStart(start);
}
void HAL_SetAddressableLEDLength(HAL_AddressableLEDHandle handle,
int32_t length, int32_t* status) {
*status = HAL_HANDLE_ERROR;
return;
auto port = smartIoHandles->Get(handle, HAL_HandleEnum::AddressableLED);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
*status = port->SetLedLength(length);
}
static_assert(sizeof(HAL_AddressableLEDData) == sizeof(uint32_t),
"LED Data must be 32 bit");
static_assert(sizeof(HAL_AddressableLEDData) == 3, "LED Data must be 3 bytes");
void HAL_WriteAddressableLEDData(HAL_AddressableLEDHandle handle,
const struct HAL_AddressableLEDData* data,
int32_t length, int32_t* status) {
*status = HAL_HANDLE_ERROR;
return;
}
void HAL_SetAddressableLEDBitTiming(HAL_AddressableLEDHandle handle,
int32_t highTime0, int32_t lowTime0,
int32_t highTime1, int32_t lowTime1,
int32_t* status) {
*status = HAL_HANDLE_ERROR;
return;
}
void HAL_SetAddressableLEDSyncTime(HAL_AddressableLEDHandle handle,
int32_t syncTime, int32_t* status) {
*status = HAL_HANDLE_ERROR;
return;
}
void HAL_StartAddressableLEDOutput(HAL_AddressableLEDHandle handle,
int32_t* status) {
*status = HAL_HANDLE_ERROR;
return;
}
void HAL_StopAddressableLEDOutput(HAL_AddressableLEDHandle handle,
int32_t* status) {
*status = HAL_HANDLE_ERROR;
return;
void HAL_SetAddressableLEDData(int32_t start, int32_t length,
HAL_AddressableLEDColorOrder colorOrder,
const struct HAL_AddressableLEDData* data,
int32_t* status) {
if (start < 0 || start >= HAL_kAddressableLEDMaxLength || length < 0 ||
(start + length) >= HAL_kAddressableLEDMaxLength) {
*status = PARAMETER_OUT_OF_RANGE;
return;
}
// TODO: handle color order
std::memcpy(&leds->s_buffer[start * 3], data, length * 3);
leds->rawPub.Set(leds->s_buffer);
}
} // extern "C"

View File

@@ -29,7 +29,7 @@ constexpr int32_t kNumCTREPDPChannels = 16;
constexpr int32_t kNumREVPDHModules = 63;
constexpr int32_t kNumREVPDHChannels = 24;
constexpr int32_t kNumDutyCycles = 0;
constexpr int32_t kNumAddressableLEDs = 0;
constexpr int32_t kNumAddressableLEDs = 6;
constexpr int32_t kNumREVPHModules = 63;
constexpr int32_t kNumREVPHChannels = 16;

View File

@@ -8,6 +8,8 @@
#include "HALInitializer.h"
#include "SystemServerInternal.h"
#include "hal/AddressableLEDTypes.h"
#include "hal/Errors.h"
namespace hal {
@@ -42,6 +44,10 @@ int32_t SmartIo::InitializeMode(SmartIoMode mode) {
inst.GetIntegerTopic(subTableString + "valset").Publish(options);
periodSetPublisher =
inst.GetIntegerTopic(subTableString + "periodset").Publish(options);
ledcountPublisher =
inst.GetIntegerTopic(subTableString + "ledcount").Publish(options);
ledoffsetPublisher =
inst.GetIntegerTopic(subTableString + "ledoffset").Publish(options);
currentMode = mode;
switch (mode) {
@@ -50,6 +56,10 @@ int32_t SmartIo::InitializeMode(SmartIoMode mode) {
case SmartIoMode::PwmOutput:
setPublisher.Set(0);
break;
case SmartIoMode::AddressableLED:
ledcountPublisher.Set(0);
ledoffsetPublisher.Set(0);
break;
// These don't need to set any value
case SmartIoMode::DigitalInput:
@@ -189,4 +199,26 @@ int32_t SmartIo::GetCounter(int32_t* value) {
return 0;
}
int32_t SmartIo::SetLedStart(int32_t start) {
if (currentMode != SmartIoMode::AddressableLED) {
return INCOMPATIBLE_STATE;
}
if (start < 0 || start >= HAL_kAddressableLEDMaxLength) {
return PARAMETER_OUT_OF_RANGE;
}
ledoffsetPublisher.Set(start);
return 0;
}
int32_t SmartIo::SetLedLength(int32_t length) {
if (currentMode != SmartIoMode::AddressableLED) {
return INCOMPATIBLE_STATE;
}
if (length < 0 || length >= HAL_kAddressableLEDMaxLength) {
return PARAMETER_OUT_OF_RANGE;
}
ledcountPublisher.Set(length);
return 0;
}
} // namespace hal

View File

@@ -25,6 +25,7 @@ enum class SmartIoMode {
PwmOutput = 4,
SingleCounterRising = 5,
SingleCounterFalling = 6,
AddressableLED = 13,
};
enum class PwmOutputPeriod {
@@ -46,6 +47,9 @@ struct SmartIo {
nt::IntegerPublisher periodSetPublisher;
nt::IntegerSubscriber periodGetSubscriber;
nt::IntegerPublisher ledcountPublisher;
nt::IntegerPublisher ledoffsetPublisher;
int32_t InitializeMode(SmartIoMode mode);
int32_t SwitchDioDirection(bool input);
@@ -63,6 +67,9 @@ struct SmartIo {
int32_t GetAnalogInput(uint16_t* value);
int32_t GetCounter(int32_t* count);
int32_t SetLedStart(int32_t start);
int32_t SetLedLength(int32_t length);
};
extern DigitalHandleResource<HAL_DigitalHandle, SmartIo, kNumSmartIo>*

View File

@@ -8,32 +8,27 @@
extern "C" {
int32_t HALSIM_FindAddressableLEDForChannel(int32_t channel) {
return 0;
}
void HALSIM_ResetAddressableLEDData(int32_t index) {}
int32_t HALSIM_GetAddressableLEDData(int32_t index,
int32_t HALSIM_GetAddressableLEDData(int32_t start, int32_t length,
struct HAL_AddressableLEDData* data) {
return 0;
}
void HALSIM_SetAddressableLEDData(int32_t index,
const struct HAL_AddressableLEDData* data,
int32_t length) {}
void HALSIM_SetAddressableLEDData(int32_t start, int32_t length,
const struct HAL_AddressableLEDData* data) {}
#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, AddressableLED##CAPINAME, RETURN)
DEFINE_CAPI(HAL_Bool, Initialized, false)
DEFINE_CAPI(int32_t, OutputPort, 0)
DEFINE_CAPI(int32_t, Start, 0)
DEFINE_CAPI(int32_t, Length, 0)
DEFINE_CAPI(HAL_Bool, Running, false)
#undef DEFINE_CAPI
#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
HAL_SIMCALLBACKREGISTRY_STUB_CAPI(TYPE, HALSIM, AddressableLED##CAPINAME)
#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
HAL_SIMCALLBACKREGISTRY_STUB_CAPI_NOINDEX(TYPE, HALSIM, \
AddressableLED##CAPINAME)
DEFINE_CAPI(HAL_ConstBufferCallback, Data, data)