diff --git a/hal/include/HAL/AnalogOutput.h b/hal/include/HAL/AnalogOutput.h index 752917bf29..298d48d84d 100644 --- a/hal/include/HAL/AnalogOutput.h +++ b/hal/include/HAL/AnalogOutput.h @@ -11,11 +11,15 @@ #include "Handles.h" +typedef HalHandle HalAnalogOutputHandle; + extern "C" { -void* initializeAnalogOutputPort(HalPortHandle port_handle, int32_t* status); -void freeAnalogOutputPort(void* analog_port_pointer); -void setAnalogOutput(void* analog_port_pointer, double voltage, +HalAnalogOutputHandle initializeAnalogOutputPort(HalPortHandle port_handle, + int32_t* status); +void freeAnalogOutputPort(HalAnalogOutputHandle analog_output_handle); +void setAnalogOutput(HalAnalogOutputHandle analog_output_handle, double voltage, int32_t* status); -double getAnalogOutput(void* analog_port_pointer, int32_t* status); +double getAnalogOutput(HalAnalogOutputHandle analog_output_handle, + int32_t* status); bool checkAnalogOutputChannel(uint32_t pin); } diff --git a/hal/lib/athena/AnalogOutput.cpp b/hal/lib/athena/AnalogOutput.cpp index 73e0aeb206..034accbaac 100644 --- a/hal/lib/athena/AnalogOutput.cpp +++ b/hal/lib/athena/AnalogOutput.cpp @@ -10,37 +10,55 @@ #include "AnalogInternal.h" #include "HAL/Errors.h" #include "handles/HandlesInternal.h" +#include "handles/IndexedHandleResource.h" using namespace hal; +namespace { +struct AnalogOutput { + uint8_t pin; +}; +} + +static IndexedHandleResource + analogOutputHandles; + extern "C" { /** * Initialize the analog output port using the given port object. */ -void* initializeAnalogOutputPort(HalPortHandle port_handle, int32_t* status) { +HalAnalogOutputHandle initializeAnalogOutputPort(HalPortHandle port_handle, + int32_t* status) { initializeAnalog(status); - if (*status != 0) return nullptr; + if (*status != 0) return HAL_INVALID_HANDLE; int16_t pin = getPortHandlePin(port_handle); if (pin == InvalidHandleIndex) { *status = PARAMETER_OUT_OF_RANGE; - return nullptr; + return HAL_INVALID_HANDLE; } - // Initialize port structure - AnalogPort* analog_port = new AnalogPort(); - analog_port->pin = (uint8_t)pin; - analog_port->accumulator = nullptr; - return analog_port; + HalAnalogOutputHandle handle = analogOutputHandles.Allocate(pin, status); + + if (*status != 0) + return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. + + auto port = analogOutputHandles.Get(handle); + if (port == nullptr) { // would only error on thread issue + *status = PARAMETER_OUT_OF_RANGE; + return HAL_INVALID_HANDLE; + } + + port->pin = static_cast(pin); + return handle; } -void freeAnalogOutputPort(void* analog_port_pointer) { - AnalogPort* port = (AnalogPort*)analog_port_pointer; - if (!port) return; - delete port->accumulator; - delete port; +void freeAnalogOutputPort(HalAnalogOutputHandle analog_output_handle) { + // no status, so no need to check for a proper free. + analogOutputHandles.Free(analog_output_handle); } /** @@ -55,9 +73,13 @@ bool checkAnalogOutputChannel(uint32_t pin) { return false; } -void setAnalogOutput(void* analog_port_pointer, double voltage, +void setAnalogOutput(HalAnalogOutputHandle analog_output_handle, double voltage, int32_t* status) { - AnalogPort* port = (AnalogPort*)analog_port_pointer; + auto port = analogOutputHandles.Get(analog_output_handle); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } uint16_t rawValue = (uint16_t)(voltage / 5.0 * 0x1000); @@ -69,8 +91,13 @@ void setAnalogOutput(void* analog_port_pointer, double voltage, analogOutputSystem->writeMXP(port->pin, rawValue, status); } -double getAnalogOutput(void* analog_port_pointer, int32_t* status) { - AnalogPort* port = (AnalogPort*)analog_port_pointer; +double getAnalogOutput(HalAnalogOutputHandle analog_output_handle, + int32_t* status) { + auto port = analogOutputHandles.Get(analog_output_handle); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0.0; + } uint16_t rawValue = analogOutputSystem->readMXP(port->pin, status); diff --git a/hal/lib/athena/handles/HandlesInternal.h b/hal/lib/athena/handles/HandlesInternal.h index e668ca1424..821d2033e9 100644 --- a/hal/lib/athena/handles/HandlesInternal.h +++ b/hal/lib/athena/handles/HandlesInternal.h @@ -30,7 +30,8 @@ enum class HalHandleEnum { DIO = 1, Port = 2, Notifier = 3, - Interrupt = 4 + Interrupt = 4, + AnalogOutput = 5 }; static inline int16_t getHandleIndex(HalHandle handle) { diff --git a/wpilibc/athena/include/AnalogOutput.h b/wpilibc/athena/include/AnalogOutput.h index ff8861b953..a4707d2660 100644 --- a/wpilibc/athena/include/AnalogOutput.h +++ b/wpilibc/athena/include/AnalogOutput.h @@ -11,6 +11,7 @@ #include +#include "HAL/AnalogOutput.h" #include "LiveWindow/LiveWindowSendable.h" #include "SensorBase.h" @@ -34,7 +35,7 @@ class AnalogOutput : public SensorBase, public LiveWindowSendable { protected: uint32_t m_channel; - void* m_port; + HalAnalogOutputHandle m_port; std::shared_ptr m_table; }; diff --git a/wpilibc/athena/src/AnalogOutput.cpp b/wpilibc/athena/src/AnalogOutput.cpp index 4b16ad3a98..cb49441eba 100644 --- a/wpilibc/athena/src/AnalogOutput.cpp +++ b/wpilibc/athena/src/AnalogOutput.cpp @@ -8,14 +8,11 @@ #include "AnalogOutput.h" #include "HAL/HAL.h" #include "LiveWindow/LiveWindow.h" -#include "Resource.h" #include "WPIErrors.h" #include #include -static std::unique_ptr outputs; - /** * Construct an analog output on the given channel. * @@ -24,23 +21,13 @@ static std::unique_ptr outputs; * @param channel The channel number on the roboRIO to represent. */ AnalogOutput::AnalogOutput(uint32_t channel) { - Resource::CreateResourceObject(outputs, kAnalogOutputs); - std::stringstream buf; buf << "analog input " << channel; if (!checkAnalogOutputChannel(channel)) { wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str()); m_channel = std::numeric_limits::max(); - m_port = nullptr; - return; - } - - if (outputs->Allocate(channel, buf.str()) == - std::numeric_limits::max()) { - CloneError(*outputs); - m_channel = std::numeric_limits::max(); - m_port = nullptr; + m_port = HAL_INVALID_HANDLE; return; } @@ -49,8 +36,13 @@ AnalogOutput::AnalogOutput(uint32_t channel) { HalPortHandle port = getPort(m_channel); int32_t status = 0; m_port = initializeAnalogOutputPort(port, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); freePort(port); + if (status != 0) { + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_channel = std::numeric_limits::max(); + m_port = HAL_INVALID_HANDLE; + return; + } LiveWindow::GetInstance()->AddActuator("AnalogOutput", m_channel, this); HALReport(HALUsageReporting::kResourceType_AnalogOutput, m_channel); @@ -61,10 +53,7 @@ AnalogOutput::AnalogOutput(uint32_t channel) { * * Frees analog output resource. */ -AnalogOutput::~AnalogOutput() { - freeAnalogOutputPort(m_port); - outputs->Free(m_channel); -} +AnalogOutput::~AnalogOutput() { freeAnalogOutputPort(m_port); } /** * Set the value of the analog output. diff --git a/wpilibj/src/athena/cpp/lib/AnalogJNI.cpp b/wpilibj/src/athena/cpp/lib/AnalogJNI.cpp index 7bcb676c00..f441469108 100644 --- a/wpilibj/src/athena/cpp/lib/AnalogJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/AnalogJNI.cpp @@ -60,16 +60,16 @@ Java_edu_wpi_first_wpilibj_hal_AnalogJNI_freeAnalogInputPort( /* * Class: edu_wpi_first_wpilibj_hal_AnalogJNI * Method: initializeAnalogOutputPort - * Signature: (I)J + * Signature: (I)I */ -JNIEXPORT jlong JNICALL +JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_AnalogJNI_initializeAnalogOutputPort( JNIEnv *env, jclass, jint id) { ANALOGJNI_LOG(logDEBUG) << "Port Handle = " << (HalPortHandle)id; int32_t status = 0; - void *analog = initializeAnalogOutputPort((HalPortHandle)id, &status); + HalAnalogOutputHandle analog = initializeAnalogOutputPort((HalPortHandle)id, &status); ANALOGJNI_LOG(logDEBUG) << "Status = " << status; - ANALOGJNI_LOG(logDEBUG) << "Analog Ptr = " << analog; + ANALOGJNI_LOG(logDEBUG) << "Analog Handle = " << analog; CheckStatus(env, status); return (jlong)analog; } @@ -77,13 +77,13 @@ Java_edu_wpi_first_wpilibj_hal_AnalogJNI_initializeAnalogOutputPort( /* * Class: edu_wpi_first_wpilibj_hal_AnalogJNI * Method: freeAnalogOutputPort - * Signature: (J)V + * Signature: (I)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_AnalogJNI_freeAnalogOutputPort( - JNIEnv *env, jclass, jlong id) { - ANALOGJNI_LOG(logDEBUG) << "Port Ptr = " << (void *)id; - freeAnalogOutputPort((void *)id); + JNIEnv *env, jclass, jint id) { + ANALOGJNI_LOG(logDEBUG) << "Port Handle = " << id; + freeAnalogOutputPort((HalAnalogOutputHandle)id); } /* @@ -134,28 +134,28 @@ Java_edu_wpi_first_wpilibj_hal_AnalogJNI_checkAnalogOutputChannel( /* * Class: edu_wpi_first_wpilibj_hal_AnalogJNI * Method: setAnalogOutput - * Signature: (JD)V + * Signature: (ID)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_AnalogJNI_setAnalogOutput( - JNIEnv *env, jclass, jlong id, jdouble voltage) { + JNIEnv *env, jclass, jint id, jdouble voltage) { ANALOGJNI_LOG(logDEBUG) << "Calling setAnalogOutput"; ANALOGJNI_LOG(logDEBUG) << "Voltage = " << voltage; - ANALOGJNI_LOG(logDEBUG) << "Analog Ptr = " << (void *)id; + ANALOGJNI_LOG(logDEBUG) << "Analog Handle = " << id; int32_t status = 0; - setAnalogOutput((void *)id, voltage, &status); + setAnalogOutput((HalAnalogOutputHandle)id, voltage, &status); CheckStatus(env, status); } /* * Class: edu_wpi_first_wpilibj_hal_AnalogJNI * Method: getAnalogOutput - * Signature: (J)D + * Signature: (I)D */ JNIEXPORT jdouble JNICALL Java_edu_wpi_first_wpilibj_hal_AnalogJNI_getAnalogOutput( - JNIEnv *env, jclass, jlong id) { + JNIEnv *env, jclass, jint id) { int32_t status = 0; - double val = getAnalogOutput((void *)id, &status); + double val = getAnalogOutput((HalAnalogOutputHandle)id, &status); CheckStatus(env, status); return val; } diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/AnalogOutput.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/AnalogOutput.java index 3ccf2a8933..3b80b7459e 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/AnalogOutput.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/AnalogOutput.java @@ -14,14 +14,12 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindow; import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable; import edu.wpi.first.wpilibj.tables.ITable; import edu.wpi.first.wpilibj.util.AllocationException; -import edu.wpi.first.wpilibj.util.CheckedAllocationException; /** * Analog output class. */ public class AnalogOutput extends SensorBase implements LiveWindowSendable { - private static Resource channels = new Resource(kAnalogOutputChannels); - private long m_port; + private int m_port; private int m_channel; /** @@ -36,14 +34,10 @@ public class AnalogOutput extends SensorBase implements LiveWindowSendable { throw new AllocationException("Analog output channel " + m_channel + " cannot be allocated. Channel is not present."); } - try { - channels.allocate(channel); - } catch (CheckedAllocationException ex) { - throw new AllocationException("Analog output channel " + m_channel + " is already allocated"); - } final int portHandle = AnalogJNI.getPort((byte) channel); m_port = AnalogJNI.initializeAnalogOutputPort(portHandle); + AnalogJNI.freePort(portHandle); LiveWindow.addSensor("AnalogOutput", channel, this); UsageReporting.report(tResourceType.kResourceType_AnalogOutput, channel); @@ -55,7 +49,6 @@ public class AnalogOutput extends SensorBase implements LiveWindowSendable { public void free() { AnalogJNI.freeAnalogOutputPort(m_port); m_port = 0; - channels.free(m_channel); m_channel = 0; } diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/AnalogJNI.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/AnalogJNI.java index f53990f4f7..45ee90a78b 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/AnalogJNI.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/AnalogJNI.java @@ -37,9 +37,9 @@ public class AnalogJNI extends JNIWrapper { public static native void freeAnalogInputPort(long portPointer); - public static native long initializeAnalogOutputPort(int halPortHandle); + public static native int initializeAnalogOutputPort(int halPortHandle); - public static native void freeAnalogOutputPort(long portPointer); + public static native void freeAnalogOutputPort(int portHandle); public static native boolean checkAnalogModule(byte module); @@ -47,9 +47,9 @@ public class AnalogJNI extends JNIWrapper { public static native boolean checkAnalogOutputChannel(int pin); - public static native void setAnalogOutput(long portPointer, double voltage); + public static native void setAnalogOutput(int portHandle, double voltage); - public static native double getAnalogOutput(long portPointer); + public static native double getAnalogOutput(int portHandle); public static native void setAnalogSampleRate(double samplesPerSecond);