2020-12-26 14:12:05 -08:00
|
|
|
// 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.
|
2019-11-17 16:39:38 -08:00
|
|
|
|
|
|
|
|
#include <jni.h>
|
|
|
|
|
|
|
|
|
|
#include "HALUtil.h"
|
2025-11-07 19:55:43 -05:00
|
|
|
#include "org_wpilib_hardware_hal_AddressableLEDJNI.h"
|
2025-11-07 19:56:21 -05:00
|
|
|
#include "wpi/hal/AddressableLED.h"
|
2025-11-07 19:57:55 -05:00
|
|
|
#include "wpi/util/jni_util.hpp"
|
2019-11-17 16:39:38 -08:00
|
|
|
|
2020-06-26 17:12:55 -07:00
|
|
|
using namespace hal;
|
2019-11-17 16:39:38 -08:00
|
|
|
using namespace wpi::java;
|
|
|
|
|
|
2025-07-21 21:52:10 -07:00
|
|
|
static_assert(sizeof(jbyte) * 3 == sizeof(HAL_AddressableLEDData));
|
2019-11-17 15:05:56 -08:00
|
|
|
|
2025-11-07 19:55:43 -05:00
|
|
|
static_assert(org_wpilib_hardware_hal_AddressableLEDJNI_COLOR_ORDER_RGB ==
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
HAL_ALED_RGB);
|
2025-11-07 19:55:43 -05:00
|
|
|
static_assert(org_wpilib_hardware_hal_AddressableLEDJNI_COLOR_ORDER_RBG ==
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
HAL_ALED_RBG);
|
2025-11-07 19:55:43 -05:00
|
|
|
static_assert(org_wpilib_hardware_hal_AddressableLEDJNI_COLOR_ORDER_BGR ==
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
HAL_ALED_BGR);
|
2025-11-07 19:55:43 -05:00
|
|
|
static_assert(org_wpilib_hardware_hal_AddressableLEDJNI_COLOR_ORDER_BRG ==
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
HAL_ALED_BRG);
|
2025-11-07 19:55:43 -05:00
|
|
|
static_assert(org_wpilib_hardware_hal_AddressableLEDJNI_COLOR_ORDER_GBR ==
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
HAL_ALED_GBR);
|
2025-11-07 19:55:43 -05:00
|
|
|
static_assert(org_wpilib_hardware_hal_AddressableLEDJNI_COLOR_ORDER_GRB ==
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
HAL_ALED_GRB);
|
|
|
|
|
|
2019-11-17 16:39:38 -08:00
|
|
|
extern "C" {
|
|
|
|
|
/*
|
2025-11-07 19:55:43 -05:00
|
|
|
* Class: org_wpilib_hardware_hal_AddressableLEDJNI
|
2019-11-17 16:39:38 -08:00
|
|
|
* Method: initialize
|
|
|
|
|
* Signature: (I)I
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jint JNICALL
|
2025-11-07 19:55:43 -05:00
|
|
|
Java_org_wpilib_hardware_hal_AddressableLEDJNI_initialize
|
2025-07-21 21:52:10 -07:00
|
|
|
(JNIEnv* env, jclass, jint channel)
|
2019-11-17 16:39:38 -08:00
|
|
|
{
|
|
|
|
|
int32_t status = 0;
|
2025-07-21 21:52:10 -07:00
|
|
|
auto stack = wpi::java::GetJavaStackTrace(env, "edu.wpi.first");
|
|
|
|
|
auto ret = HAL_InitializeAddressableLED(channel, stack.c_str(), &status);
|
|
|
|
|
CheckStatusForceThrow(env, status);
|
2019-11-17 16:39:38 -08:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2025-11-07 19:55:43 -05:00
|
|
|
* Class: org_wpilib_hardware_hal_AddressableLEDJNI
|
2019-11-17 16:39:38 -08:00
|
|
|
* Method: free
|
|
|
|
|
* Signature: (I)V
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2025-11-07 19:55:43 -05:00
|
|
|
Java_org_wpilib_hardware_hal_AddressableLEDJNI_free
|
2019-11-17 16:39:38 -08:00
|
|
|
(JNIEnv* env, jclass, jint handle)
|
|
|
|
|
{
|
2024-09-07 13:58:15 -04:00
|
|
|
if (handle != HAL_kInvalidHandle) {
|
|
|
|
|
HAL_FreeAddressableLED(static_cast<HAL_AddressableLEDHandle>(handle));
|
|
|
|
|
}
|
2019-11-17 16:39:38 -08:00
|
|
|
}
|
|
|
|
|
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
/*
|
2025-11-07 19:55:43 -05:00
|
|
|
* Class: org_wpilib_hardware_hal_AddressableLEDJNI
|
2025-07-21 21:52:10 -07:00
|
|
|
* Method: setStart
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
* Signature: (II)V
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2025-11-07 19:55:43 -05:00
|
|
|
Java_org_wpilib_hardware_hal_AddressableLEDJNI_setStart
|
2025-07-21 21:52:10 -07:00
|
|
|
(JNIEnv* env, jclass, jint handle, jint start)
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
{
|
|
|
|
|
int32_t status = 0;
|
2025-07-21 21:52:10 -07:00
|
|
|
HAL_SetAddressableLEDStart(static_cast<HAL_AddressableLEDHandle>(handle),
|
|
|
|
|
start, &status);
|
[hal, wpilib] AddressableLED: add support for other color orders (#7102)
Many LED strips use different color order (GRB in particular is common).
This makes the change at the HAL level. This solves 2 problems; first, no code needs to change in the high level drivers, which was challenging for C++, and second, simulation will behave properly as no conversion is needed. The HAL will accept an array of data objects in the same order no matter what the selected output order is, and will convert before sending it to the FPGA for output.
To accomplish this, NEON bulk load/interleave instructions are utilized. The low level implementation (load, store, and alignment functions) come from the Simd Library. The high level implementations are inspired by the image conversion functions in the simd library, but have diverged significantly.
Much of the implementation uses templates and inlined functions rather than runtime parameters; This is a trade off between the size of the generated code and the amount of function calls done at runtime. Currently, the entire conversion operation is inlined.
2025-02-07 15:36:41 -05:00
|
|
|
CheckStatus(env, status);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-17 16:39:38 -08:00
|
|
|
/*
|
2025-11-07 19:55:43 -05:00
|
|
|
* Class: org_wpilib_hardware_hal_AddressableLEDJNI
|
2019-11-17 16:39:38 -08:00
|
|
|
* Method: setLength
|
|
|
|
|
* Signature: (II)V
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2025-11-07 19:55:43 -05:00
|
|
|
Java_org_wpilib_hardware_hal_AddressableLEDJNI_setLength
|
2019-11-17 16:39:38 -08:00
|
|
|
(JNIEnv* env, jclass, jint handle, jint length)
|
|
|
|
|
{
|
|
|
|
|
int32_t status = 0;
|
|
|
|
|
HAL_SetAddressableLEDLength(static_cast<HAL_AddressableLEDHandle>(handle),
|
|
|
|
|
length, &status);
|
|
|
|
|
CheckStatus(env, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2025-11-07 19:55:43 -05:00
|
|
|
* Class: org_wpilib_hardware_hal_AddressableLEDJNI
|
2019-11-17 16:39:38 -08:00
|
|
|
* Method: setData
|
2025-07-21 21:52:10 -07:00
|
|
|
* Signature: (II[BII)V
|
2019-11-17 16:39:38 -08:00
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2025-11-07 19:55:43 -05:00
|
|
|
Java_org_wpilib_hardware_hal_AddressableLEDJNI_setData
|
2025-07-21 21:52:10 -07:00
|
|
|
(JNIEnv* env, jclass, jint outStart, jint colorOrder, jbyteArray data,
|
|
|
|
|
jint start, jint len)
|
2019-11-17 16:39:38 -08:00
|
|
|
{
|
2025-07-21 21:52:10 -07:00
|
|
|
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);
|
2019-11-17 16:39:38 -08:00
|
|
|
int32_t status = 0;
|
2025-07-21 21:52:10 -07:00
|
|
|
HAL_SetAddressableLEDData(
|
|
|
|
|
outStart, rawdata.size() / 3,
|
|
|
|
|
static_cast<HAL_AddressableLEDColorOrder>(colorOrder),
|
|
|
|
|
reinterpret_cast<const HAL_AddressableLEDData*>(rawdata.data()), &status);
|
2019-11-17 16:39:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2025-11-07 19:55:43 -05:00
|
|
|
* Class: org_wpilib_hardware_hal_AddressableLEDJNI
|
2025-07-21 21:52:10 -07:00
|
|
|
* Method: setDataFromBuffer
|
|
|
|
|
* Signature: (IILjava/lang/Object;II)V
|
2019-11-17 16:39:38 -08:00
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2025-11-07 19:55:43 -05:00
|
|
|
Java_org_wpilib_hardware_hal_AddressableLEDJNI_setDataFromBuffer
|
2025-07-21 21:52:10 -07:00
|
|
|
(JNIEnv* env, jclass, jint outStart, jint colorOrder, jobject data,
|
|
|
|
|
jint start, jint len)
|
2019-11-17 16:39:38 -08:00
|
|
|
{
|
2025-07-21 21:52:10 -07:00
|
|
|
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);
|
2019-11-17 16:39:38 -08:00
|
|
|
int32_t status = 0;
|
2025-07-21 21:52:10 -07:00
|
|
|
HAL_SetAddressableLEDData(
|
|
|
|
|
outStart, rawdata.size() / 3,
|
|
|
|
|
static_cast<HAL_AddressableLEDColorOrder>(colorOrder),
|
|
|
|
|
reinterpret_cast<const HAL_AddressableLEDData*>(rawdata.data()), &status);
|
2019-11-17 16:39:38 -08:00
|
|
|
}
|
|
|
|
|
} // extern "C"
|