diff --git a/hal/include/HAL/DIO.h b/hal/include/HAL/DIO.h index 22cbd0ea78..ae121ee581 100644 --- a/hal/include/HAL/DIO.h +++ b/hal/include/HAL/DIO.h @@ -12,10 +12,9 @@ #include "Handles.h" extern "C" { -// the following 2 functions are here as they will be changed with -// the handle changes to be DIO exclusive. -void* initializeDigitalPort(HalPortHandle port_handle, int32_t* status); -void freeDigitalPort(void* digital_port_pointer); +HalDigitalHandle initializeDIOPort(HalPortHandle port_handle, uint8_t input, + int32_t* status); +void freeDIOPort(HalDigitalHandle dio_port_handle); void* allocatePWM(int32_t* status); void freePWM(void* pwmGenerator, int32_t* status); @@ -23,18 +22,17 @@ void setPWMRate(double rate, int32_t* status); void setPWMDutyCycle(void* pwmGenerator, double dutyCycle, int32_t* status); void setPWMOutputChannel(void* pwmGenerator, uint32_t pin, int32_t* status); -bool allocateDIO(void* digital_port_pointer, bool input, int32_t* status); -void freeDIO(void* digital_port_pointer, int32_t* status); -void setDIO(void* digital_port_pointer, short value, int32_t* status); -bool getDIO(void* digital_port_pointer, int32_t* status); -bool getDIODirection(void* digital_port_pointer, int32_t* status); -void pulse(void* digital_port_pointer, double pulseLength, int32_t* status); -bool isPulsing(void* digital_port_pointer, int32_t* status); +void setDIO(HalDigitalHandle dio_port_handle, short value, int32_t* status); +bool getDIO(HalDigitalHandle dio_port_handle, int32_t* status); +bool getDIODirection(HalDigitalHandle dio_port_handle, int32_t* status); +void pulse(HalDigitalHandle dio_port_handle, double pulseLength, + int32_t* status); +bool isPulsing(HalDigitalHandle dio_port_handle, int32_t* status); bool isAnyPulsing(int32_t* status); -void setFilterSelect(void* digital_port_pointer, int filter_index, +void setFilterSelect(HalDigitalHandle dio_port_handle, int filter_index, int32_t* status); -int getFilterSelect(void* digital_port_pointer, int32_t* status); +int getFilterSelect(HalDigitalHandle dio_port_handle, int32_t* status); void setFilterPeriod(int filter_index, uint32_t value, int32_t* status); uint32_t getFilterPeriod(int filter_index, int32_t* status); diff --git a/hal/include/HAL/Handles.h b/hal/include/HAL/Handles.h index 57aae1af32..6a9317bbda 100644 --- a/hal/include/HAL/Handles.h +++ b/hal/include/HAL/Handles.h @@ -26,3 +26,5 @@ typedef HalHandle HalAnalogInputHandle; typedef HalHandle HalAnalogTriggerHandle; typedef HalHandle HalRelayHandle; + +typedef HalHandle HalDigitalHandle; diff --git a/hal/include/HAL/PWM.h b/hal/include/HAL/PWM.h index fb75cb8d65..018222a36f 100644 --- a/hal/include/HAL/PWM.h +++ b/hal/include/HAL/PWM.h @@ -9,15 +9,19 @@ #include -extern "C" { -bool checkPWMChannel(void* digital_port_pointer); +#include "HAL/Handles.h" -void setPWM(void* digital_port_pointer, unsigned short value, int32_t* status); -bool allocatePWMChannel(void* digital_port_pointer, int32_t* status); -void freePWMChannel(void* digital_port_pointer, int32_t* status); -unsigned short getPWM(void* digital_port_pointer, int32_t* status); -void latchPWMZero(void* digital_port_pointer, int32_t* status); -void setPWMPeriodScale(void* digital_port_pointer, uint32_t squelchMask, +extern "C" { +HalDigitalHandle initializePWMPort(HalPortHandle port_handle, int32_t* status); +void freePWMPort(HalDigitalHandle pwm_port_handle, int32_t* status); + +bool checkPWMChannel(uint8_t pin); + +void setPWM(HalDigitalHandle pwm_port_handle, unsigned short value, + int32_t* status); +unsigned short getPWM(HalDigitalHandle pwm_port_handle, int32_t* status); +void latchPWMZero(HalDigitalHandle pwm_port_handle, int32_t* status); +void setPWMPeriodScale(HalDigitalHandle pwm_port_handle, uint32_t squelchMask, int32_t* status); uint16_t getLoopTiming(int32_t* status); } diff --git a/hal/lib/athena/DIO.cpp b/hal/lib/athena/DIO.cpp index 1326635b25..4eabc0e558 100644 --- a/hal/lib/athena/DIO.cpp +++ b/hal/lib/athena/DIO.cpp @@ -25,27 +25,69 @@ extern "C" { /** * Create a new instance of a digital port. */ -void* initializeDigitalPort(HalPortHandle port_handle, int32_t* status) { +HalDigitalHandle initializeDIOPort(HalPortHandle port_handle, uint8_t input, + int32_t* status) { initializeDigital(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 - DigitalPort* digital_port = new DigitalPort(); - digital_port->pin = (uint8_t)pin; + auto handle = digitalPinHandles.Allocate(pin, HalHandleEnum::DIO, status); - return digital_port; + if (*status != 0) + return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. + + auto port = digitalPinHandles.Get(handle, HalHandleEnum::DIO); + if (port == nullptr) { // would only occur on thread issue. + *status = PARAMETER_OUT_OF_RANGE; + return HAL_INVALID_HANDLE; + } + + port->pin = static_cast(pin); + + std::lock_guard sync(digitalDIOMutex); + + tDIO::tOutputEnable outputEnable = digitalSystem->readOutputEnable(status); + + if (port->pin < kNumHeaders) { + uint32_t bitToSet = 1 << port->pin; + if (input) { + outputEnable.Headers = + outputEnable.Headers & (~bitToSet); // clear the bit for read + } else { + outputEnable.Headers = + outputEnable.Headers | bitToSet; // set the bit for write + } + } else { + uint32_t bitToSet = 1 << remapMXPChannel(port->pin); + + // Disable special functions on this pin + short specialFunctions = + digitalSystem->readEnableMXPSpecialFunction(status); + digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToSet, + status); + + if (input) { + outputEnable.MXP = + outputEnable.MXP & (~bitToSet); // clear the bit for read + } else { + outputEnable.MXP = outputEnable.MXP | bitToSet; // set the bit for write + } + } + + digitalSystem->writeOutputEnable(outputEnable, status); + + return handle; } -void freeDigitalPort(void* digital_port_pointer) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - delete port; +void freeDIOPort(HalDigitalHandle dio_port_handle) { + // no status, so no need to check for a proper free. + digitalPinHandles.Free(dio_port_handle, HalHandleEnum::DIO); } /** @@ -133,76 +175,6 @@ void setPWMOutputChannel(void* pwmGenerator, uint32_t pin, int32_t* status) { digitalSystem->writePWMOutputSelect(id, pin, status); } -/** - * Allocate Digital I/O channels. - * Allocate channels so that they are not accidently reused. Also the direction - * is set at the time of the allocation. - * - * @param channel The Digital I/O channel - * @param input If true open as input; if false open as output - * @return Was successfully allocated - */ -bool allocateDIO(void* digital_port_pointer, bool input, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - if (port == nullptr) { - *status = NULL_PARAMETER; - return false; - } - char buf[64]; - snprintf(buf, 64, "DIO %d", port->pin); - if (DIOChannels->Allocate(port->pin, buf) == ~0ul) { - *status = RESOURCE_IS_ALLOCATED; - return false; - } - - { - std::lock_guard sync(digitalDIOMutex); - - tDIO::tOutputEnable outputEnable = digitalSystem->readOutputEnable(status); - - if (port->pin < kNumHeaders) { - uint32_t bitToSet = 1 << port->pin; - if (input) { - outputEnable.Headers = - outputEnable.Headers & (~bitToSet); // clear the bit for read - } else { - outputEnable.Headers = - outputEnable.Headers | bitToSet; // set the bit for write - } - } else { - uint32_t bitToSet = 1 << remapMXPChannel(port->pin); - - // Disable special functions on this pin - short specialFunctions = - digitalSystem->readEnableMXPSpecialFunction(status); - digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToSet, - status); - - if (input) { - outputEnable.MXP = - outputEnable.MXP & (~bitToSet); // clear the bit for read - } else { - outputEnable.MXP = - outputEnable.MXP | bitToSet; // set the bit for write - } - } - - digitalSystem->writeOutputEnable(outputEnable, status); - } - return true; -} - -/** - * Free the resource associated with a digital I/O channel. - * - * @param channel The Digital I/O channel to free - */ -void freeDIO(void* digital_port_pointer, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - if (!port) return; - DIOChannels->Free(port->pin); -} - /** * Write a digital I/O bit to the FPGA. * Set a single value on a digital I/O channel. @@ -211,8 +183,12 @@ void freeDIO(void* digital_port_pointer, int32_t* status) { * @param value The state to set the digital channel (if it is configured as an * output) */ -void setDIO(void* digital_port_pointer, short value, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; +void setDIO(HalDigitalHandle dio_port_handle, short value, int32_t* status) { + auto port = digitalPinHandles.Get(dio_port_handle, HalHandleEnum::DIO); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } if (value != 0 && value != 1) { if (value != 0) value = 1; } @@ -250,8 +226,12 @@ void setDIO(void* digital_port_pointer, short value, int32_t* status) { * @param channel The digital I/O channel * @return The state of the specified channel */ -bool getDIO(void* digital_port_pointer, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; +bool getDIO(HalDigitalHandle dio_port_handle, int32_t* status) { + auto port = digitalPinHandles.Get(dio_port_handle, HalHandleEnum::DIO); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return false; + } tDIO::tDI currentDIO = digitalSystem->readDI(status); // Shift 00000001 over channel-1 places. // AND it against the currentDIO @@ -279,8 +259,12 @@ bool getDIO(void* digital_port_pointer, int32_t* status) { * @param channel The digital I/O channel * @return The direction of the specified channel */ -bool getDIODirection(void* digital_port_pointer, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; +bool getDIODirection(HalDigitalHandle dio_port_handle, int32_t* status) { + auto port = digitalPinHandles.Get(dio_port_handle, HalHandleEnum::DIO); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return false; + } tDIO::tOutputEnable currentOutputEnable = digitalSystem->readOutputEnable(status); // Shift 00000001 over port->pin-1 places. @@ -303,8 +287,13 @@ bool getDIODirection(void* digital_port_pointer, int32_t* status) { * @param channel The Digital Output channel that the pulse should be output on * @param pulseLength The active length of the pulse (in seconds) */ -void pulse(void* digital_port_pointer, double pulseLength, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; +void pulse(HalDigitalHandle dio_port_handle, double pulseLength, + int32_t* status) { + auto port = digitalPinHandles.Get(dio_port_handle, HalHandleEnum::DIO); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } tDIO::tPulse pulse; if (port->pin < kNumHeaders) { @@ -324,8 +313,12 @@ void pulse(void* digital_port_pointer, double pulseLength, int32_t* status) { * * @return A pulse is in progress */ -bool isPulsing(void* digital_port_pointer, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; +bool isPulsing(HalDigitalHandle dio_port_handle, int32_t* status) { + auto port = digitalPinHandles.Get(dio_port_handle, HalHandleEnum::DIO); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return false; + } tDIO::tPulse pulseRegister = digitalSystem->readPulse(status); if (port->pin < kNumHeaders) { @@ -353,9 +346,13 @@ bool isAnyPulsing(int32_t* status) { * @param filter_index The filter index. Must be in the range 0 - 3, * where 0 means "none" and 1 - 3 means filter # filter_index - 1. */ -void setFilterSelect(void* digital_port_pointer, int filter_index, +void setFilterSelect(HalDigitalHandle dio_port_handle, int filter_index, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; + auto port = digitalPinHandles.Get(dio_port_handle, HalHandleEnum::DIO); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } std::lock_guard sync(digitalDIOMutex); if (port->pin < kNumHeaders) { @@ -374,8 +371,12 @@ void setFilterSelect(void* digital_port_pointer, int filter_index, * @return filter_index The filter index. Must be in the range 0 - 3, * where 0 means "none" and 1 - 3 means filter # filter_index - 1. */ -int getFilterSelect(void* digital_port_pointer, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; +int getFilterSelect(HalDigitalHandle dio_port_handle, int32_t* status) { + auto port = digitalPinHandles.Get(dio_port_handle, HalHandleEnum::DIO); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } std::lock_guard sync(digitalDIOMutex); if (port->pin < kNumHeaders) { diff --git a/hal/lib/athena/DigitalInternal.cpp b/hal/lib/athena/DigitalInternal.cpp index 2fc24d6c5d..99a43edf73 100644 --- a/hal/lib/athena/DigitalInternal.cpp +++ b/hal/lib/athena/DigitalInternal.cpp @@ -31,6 +31,9 @@ hal::Resource* PWMChannels = nullptr; bool digitalSystemsInitialized = false; +DigitalHandleResource + digitalPinHandles; + /** * Initialize the digital system. */ @@ -75,12 +78,21 @@ void initializeDigital(int32_t* status) { pwmSystem->writeConfig_MinHigh(minHigh, status); // Ensure that PWM output values are set to OFF for (uint32_t pwm_index = 0; pwm_index < kPwmPins; pwm_index++) { - // Initialize port structure - DigitalPort digital_port; - digital_port.pin = pwm_index; + // Copy of SetPWM + if (pwm_index < tPWM::kNumHdrRegisters) { + pwmSystem->writeHdr(pwm_index, kPwmDisabled, status); + } else { + pwmSystem->writeMXP(pwm_index - tPWM::kNumHdrRegisters, kPwmDisabled, + status); + } - setPWM(&digital_port, kPwmDisabled, status); - setPWMPeriodScale(&digital_port, 3, status); // Set all to 4x by default. + // Copy of SetPWMPeriodScale, set to 4x by default. + if (pwm_index < tPWM::kNumPeriodScaleHdrElements) { + pwmSystem->writePeriodScaleHdr(pwm_index, 3, status); + } else { + pwmSystem->writePeriodScaleMXP( + pwm_index - tPWM::kNumPeriodScaleHdrElements, 3, status); + } } digitalSystemsInitialized = true; diff --git a/hal/lib/athena/DigitalInternal.h b/hal/lib/athena/DigitalInternal.h index 0bbf699172..fb390fc898 100644 --- a/hal/lib/athena/DigitalInternal.h +++ b/hal/lib/athena/DigitalInternal.h @@ -10,7 +10,10 @@ #include #include "ChipObject.h" +#include "HAL/Handles.h" #include "HAL/cpp/Resource.h" +#include "handles/DigitalHandleResource.h" +#include "handles/HandlesInternal.h" namespace hal { constexpr uint32_t kNumHeaders = 10; // Number of non-MXP pins @@ -64,9 +67,12 @@ extern bool digitalSystemsInitialized; struct DigitalPort { uint8_t pin; - uint32_t PWMGeneratorID; }; +extern DigitalHandleResource + digitalPinHandles; + void initializeDigital(int32_t* status); void remapDigitalSource(bool analogTrigger, uint32_t& pin, uint8_t& module); uint32_t remapMXPPWMChannel(uint32_t pin); diff --git a/hal/lib/athena/I2C.cpp b/hal/lib/athena/I2C.cpp index 9dd4e527f3..b351be57e9 100644 --- a/hal/lib/athena/I2C.cpp +++ b/hal/lib/athena/I2C.cpp @@ -25,6 +25,9 @@ static uint8_t i2CMXPObjCount = 0; static uint8_t i2COnBoardHandle = 0; static uint8_t i2CMXPHandle = 0; +static HalDigitalHandle i2CMXPDigitalHandle1 = HAL_INVALID_HANDLE; +static HalDigitalHandle i2CMXPDigitalHandle2 = HAL_INVALID_HANDLE; + extern "C" { /* * Initialize the I2C port. Opens the port if necessary and saves the handle. @@ -51,12 +54,15 @@ void i2CInitialize(uint8_t port, int32_t* status) { } else if (port == 1) { i2CMXPObjCount++; if (i2CMXPHandle > 0) return; - if (!allocateDIO(initializeDigitalPort(getPort(24), status), false, - status)) + if ((i2CMXPDigitalHandle1 = initializeDIOPort( + getPort(24), false, status)) == HAL_INVALID_HANDLE) { return; - if (!allocateDIO(initializeDigitalPort(getPort(25), status), false, - status)) + } + if ((i2CMXPDigitalHandle2 = initializeDIOPort( + getPort(25), false, status)) == HAL_INVALID_HANDLE) { + freeDIOPort(i2CMXPDigitalHandle1); // free the first port allocated return; + } digitalSystem->writeEnableMXPSpecialFunction( digitalSystem->readEnableMXPSpecialFunction(status) | 0xC000, status); i2CMXPHandle = i2clib_open("/dev/i2c-1"); @@ -168,6 +174,11 @@ void i2CClose(uint8_t port) { i2clib_close(handle); } } + + if (port == 1) { + freeDIOPort(i2CMXPDigitalHandle1); + freeDIOPort(i2CMXPDigitalHandle2); + } return; } } diff --git a/hal/lib/athena/PWM.cpp b/hal/lib/athena/PWM.cpp index 055b032a08..f17d1d9cf0 100644 --- a/hal/lib/athena/PWM.cpp +++ b/hal/lib/athena/PWM.cpp @@ -8,6 +8,7 @@ #include "HAL/PWM.h" #include "DigitalInternal.h" +#include "handles/HandlesInternal.h" static_assert(sizeof(uint32_t) <= sizeof(void*), "This file shoves uint32_ts into pointers."); @@ -15,29 +16,65 @@ static_assert(sizeof(uint32_t) <= sizeof(void*), using namespace hal; extern "C" { -bool checkPWMChannel(void* digital_port_pointer) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - return port->pin < kPwmPins; + +HalDigitalHandle initializePWMPort(HalPortHandle port_handle, int32_t* status) { + initializeDigital(status); + + if (*status != 0) return HAL_INVALID_HANDLE; + + int16_t pin = getPortHandlePin(port_handle); + if (pin == InvalidHandleIndex) { + *status = PARAMETER_OUT_OF_RANGE; + return HAL_INVALID_HANDLE; + } + + uint8_t origPin = static_cast(pin); + + if (origPin < kNumHeaders) { + pin += kDigitalPins; // remap Headers to end of allocations + } else { + pin = remapMXPPWMChannel(pin) + 10; // remap MXP to proper channel + } + + auto handle = digitalPinHandles.Allocate(pin, HalHandleEnum::PWM, status); + + if (*status != 0) + return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. + + auto port = digitalPinHandles.Get(handle, HalHandleEnum::PWM); + if (port == nullptr) { // would only occur on thread issue. + *status = PARAMETER_OUT_OF_RANGE; + return HAL_INVALID_HANDLE; + } + + port->pin = origPin; + + uint32_t bitToSet = 1 << remapMXPPWMChannel(port->pin); + short specialFunctions = digitalSystem->readEnableMXPSpecialFunction(status); + digitalSystem->writeEnableMXPSpecialFunction(specialFunctions | bitToSet, + status); + + return handle; +} +void freePWMPort(HalDigitalHandle pwm_port_handle, int32_t* status) { + auto port = digitalPinHandles.Get(pwm_port_handle, HalHandleEnum::PWM); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + + if (port->pin > tPWM::kNumHdrRegisters - 1) { + uint32_t bitToUnset = 1 << remapMXPPWMChannel(port->pin); + short specialFunctions = + digitalSystem->readEnableMXPSpecialFunction(status); + digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToUnset, + status); + } + + digitalPinHandles.Free(pwm_port_handle, HalHandleEnum::PWM); } -/** - * Check a port to make sure that it is not nullptr and is a valid PWM port. - * - * Sets the status to contain the appropriate error. - * - * @return true if the port passed validation. - */ -static bool verifyPWMChannel(DigitalPort* port, int32_t* status) { - if (port == nullptr) { - *status = NULL_PARAMETER; - return false; - } else if (!checkPWMChannel(port)) { - *status = PARAMETER_OUT_OF_RANGE; - return false; - } else { - return true; - } -} +bool checkPWMChannel(uint8_t pin) { return pin < kPwmPins; } /** * Set a PWM channel to the desired value. The values range from 0 to 255 and @@ -47,9 +84,11 @@ static bool verifyPWMChannel(DigitalPort* port, int32_t* status) { * @param channel The PWM channel to set. * @param value The PWM value to set. */ -void setPWM(void* digital_port_pointer, unsigned short value, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - if (!verifyPWMChannel(port, status)) { +void setPWM(HalDigitalHandle pwm_port_handle, unsigned short value, + int32_t* status) { + auto port = digitalPinHandles.Get(pwm_port_handle, HalHandleEnum::PWM); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; return; } @@ -66,9 +105,10 @@ void setPWM(void* digital_port_pointer, unsigned short value, int32_t* status) { * @param channel The PWM channel to read from. * @return The raw PWM value. */ -unsigned short getPWM(void* digital_port_pointer, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - if (!verifyPWMChannel(port, status)) { +unsigned short getPWM(HalDigitalHandle pwm_port_handle, int32_t* status) { + auto port = digitalPinHandles.Get(pwm_port_handle, HalHandleEnum::PWM); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; return 0; } @@ -79,9 +119,10 @@ unsigned short getPWM(void* digital_port_pointer, int32_t* status) { } } -void latchPWMZero(void* digital_port_pointer, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - if (!verifyPWMChannel(port, status)) { +void latchPWMZero(HalDigitalHandle pwm_port_handle, int32_t* status) { + auto port = digitalPinHandles.Get(pwm_port_handle, HalHandleEnum::PWM); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; return; } @@ -95,10 +136,11 @@ void latchPWMZero(void* digital_port_pointer, int32_t* status) { * @param channel The PWM channel to configure. * @param squelchMask The 2-bit mask of outputs to squelch. */ -void setPWMPeriodScale(void* digital_port_pointer, uint32_t squelchMask, +void setPWMPeriodScale(HalDigitalHandle pwm_port_handle, uint32_t squelchMask, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - if (!verifyPWMChannel(port, status)) { + auto port = digitalPinHandles.Get(pwm_port_handle, HalHandleEnum::PWM); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; return; } @@ -110,51 +152,6 @@ void setPWMPeriodScale(void* digital_port_pointer, uint32_t squelchMask, } } -bool allocatePWMChannel(void* digital_port_pointer, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - if (!verifyPWMChannel(port, status)) { - return false; - } - - char buf[64]; - snprintf(buf, 64, "PWM %d", port->pin); - if (PWMChannels->Allocate(port->pin, buf) == ~0ul) { - *status = RESOURCE_IS_ALLOCATED; - return false; - } - - if (port->pin > tPWM::kNumHdrRegisters - 1) { - snprintf(buf, 64, "PWM %d and DIO %d", port->pin, - remapMXPPWMChannel(port->pin) + 10); - if (DIOChannels->Allocate(remapMXPPWMChannel(port->pin) + 10, buf) == ~0ul) - return false; - uint32_t bitToSet = 1 << remapMXPPWMChannel(port->pin); - short specialFunctions = - digitalSystem->readEnableMXPSpecialFunction(status); - digitalSystem->writeEnableMXPSpecialFunction(specialFunctions | bitToSet, - status); - } - return true; -} - -void freePWMChannel(void* digital_port_pointer, int32_t* status) { - DigitalPort* port = (DigitalPort*)digital_port_pointer; - if (!port) return; - if (!verifyPWMChannel(port, status)) { - return; - } - - PWMChannels->Free(port->pin); - if (port->pin > tPWM::kNumHdrRegisters - 1) { - DIOChannels->Free(remapMXPPWMChannel(port->pin) + 10); - uint32_t bitToUnset = 1 << remapMXPPWMChannel(port->pin); - short specialFunctions = - digitalSystem->readEnableMXPSpecialFunction(status); - digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToUnset, - status); - } -} - /** * Get the loop timing of the PWM system * diff --git a/hal/lib/athena/SPI.cpp b/hal/lib/athena/SPI.cpp index 9c06acc03d..21c9ebc233 100644 --- a/hal/lib/athena/SPI.cpp +++ b/hal/lib/athena/SPI.cpp @@ -28,6 +28,11 @@ static priority_recursive_mutex spiOnboardSemaphore; static priority_recursive_mutex spiMXPSemaphore; static tSPI* spiSystem; +static HalDigitalHandle spiMXPDigitalHandle1 = HAL_INVALID_HANDLE; +static HalDigitalHandle spiMXPDigitalHandle2 = HAL_INVALID_HANDLE; +static HalDigitalHandle spiMXPDigitalHandle3 = HAL_INVALID_HANDLE; +static HalDigitalHandle spiMXPDigitalHandle4 = HAL_INVALID_HANDLE; + extern "C" { struct SPIAccumulator { @@ -80,24 +85,30 @@ void spiInitialize(uint8_t port, int32_t* status) { case 4: initializeDigital(status); if (*status != 0) return; - if (!allocateDIO(initializeDigitalPort(getPort(14), status), false, - status)) { + if ((spiMXPDigitalHandle1 = initializeDIOPort( + getPort(14), false, status)) == HAL_INVALID_HANDLE) { printf("Failed to allocate DIO 14\n"); return; } - if (!allocateDIO(initializeDigitalPort(getPort(15), status), false, - status)) { + if ((spiMXPDigitalHandle2 = initializeDIOPort( + getPort(15), false, status)) == HAL_INVALID_HANDLE) { printf("Failed to allocate DIO 15\n"); + freeDIOPort(spiMXPDigitalHandle1); // free the first port allocated return; } - if (!allocateDIO(initializeDigitalPort(getPort(16), status), true, - status)) { + if ((spiMXPDigitalHandle3 = initializeDIOPort( + getPort(16), false, status)) == HAL_INVALID_HANDLE) { printf("Failed to allocate DIO 16\n"); + freeDIOPort(spiMXPDigitalHandle1); // free the first port allocated + freeDIOPort(spiMXPDigitalHandle2); // free the second port allocated return; } - if (!allocateDIO(initializeDigitalPort(getPort(17), status), false, - status)) { + if ((spiMXPDigitalHandle4 = initializeDIOPort( + getPort(17), false, status)) == HAL_INVALID_HANDLE) { printf("Failed to allocate DIO 17\n"); + freeDIOPort(spiMXPDigitalHandle1); // free the first port allocated + freeDIOPort(spiMXPDigitalHandle2); // free the second port allocated + freeDIOPort(spiMXPDigitalHandle3); // free the third port allocated return; } digitalSystem->writeEnableMXPSpecialFunction( @@ -176,6 +187,12 @@ void spiClose(uint8_t port) { } spilib_close(spiGetHandle(port)); spiSetHandle(port, 0); + if (port == 4) { + freeDIOPort(spiMXPDigitalHandle1); + freeDIOPort(spiMXPDigitalHandle2); + freeDIOPort(spiMXPDigitalHandle3); + freeDIOPort(spiMXPDigitalHandle4); + } return; } diff --git a/hal/lib/athena/handles/DigitalHandleResource.h b/hal/lib/athena/handles/DigitalHandleResource.h new file mode 100644 index 0000000000..8e6bc513e6 --- /dev/null +++ b/hal/lib/athena/handles/DigitalHandleResource.h @@ -0,0 +1,93 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2016. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#include +#include + +#include "HAL/Errors.h" +#include "HAL/Handles.h" +#include "HAL/cpp/priority_mutex.h" +#include "HandlesInternal.h" + +namespace hal { + +/** + * The DigitalHandleResource class is a way to track handles. This version + * allows a limited number of handles that are allocated by index. + * The enum value is seperate, as 2 enum values are allowed per handle + * Because they are allocated by index, each individual index holds its own + * mutex, which reduces contention heavily.] + * + * @tparam THandle The Handle Type (Must be typedefed from HalHandle) + * @tparam TStruct The struct type held by this resource + * @tparam size The number of resources allowed to be allocated + * + */ +template +class DigitalHandleResource { + friend class DigitalHandleResourceTest; + + public: + DigitalHandleResource(const DigitalHandleResource&) = delete; + DigitalHandleResource operator=(const DigitalHandleResource&) = delete; + DigitalHandleResource() = default; + THandle Allocate(int16_t index, HalHandleEnum enumValue, int32_t* status); + std::shared_ptr Get(THandle handle, HalHandleEnum enumValue); + void Free(THandle handle, HalHandleEnum enumValue); + + private: + std::shared_ptr m_structures[size]; + priority_mutex m_handleMutexes[size]; +}; + +template +THandle DigitalHandleResource::Allocate( + int16_t index, HalHandleEnum enumValue, int32_t* status) { + // don't aquire the lock if we can fail early. + if (index < 0 || index >= size) { + *status = PARAMETER_OUT_OF_RANGE; + return HAL_INVALID_HANDLE; + } + std::lock_guard sync(m_handleMutexes[index]); + // check for allocation, otherwise allocate and return a valid handle + if (m_structures[index] != nullptr) { + *status = RESOURCE_IS_ALLOCATED; + return HAL_INVALID_HANDLE; + } + m_structures[index] = std::make_shared(); + return (THandle)hal::createHandle(index, enumValue); +} + +template +std::shared_ptr DigitalHandleResource::Get( + THandle handle, HalHandleEnum enumValue) { + // get handle index, and fail early if index out of range or wrong handle + int16_t index = getHandleTypedIndex(handle, enumValue); + if (index < 0 || index >= size) { + return nullptr; + } + std::lock_guard sync(m_handleMutexes[index]); + // return structure. Null will propogate correctly, so no need to manually + // check. + return m_structures[index]; +} + +template +void DigitalHandleResource::Free( + THandle handle, HalHandleEnum enumValue) { + // get handle index, and fail early if index out of range or wrong handle + int16_t index = getHandleTypedIndex(handle, enumValue); + if (index < 0 || index >= size) return; + // lock and deallocated handle + std::lock_guard sync(m_handleMutexes[index]); + m_structures[index].reset(); +} +} diff --git a/hal/lib/athena/handles/HandlesInternal.h b/hal/lib/athena/handles/HandlesInternal.h index 18d78bac17..3a19e3ce3d 100644 --- a/hal/lib/athena/handles/HandlesInternal.h +++ b/hal/lib/athena/handles/HandlesInternal.h @@ -34,7 +34,8 @@ enum class HalHandleEnum { AnalogOutput = 5, AnalogInput = 6, AnalogTrigger = 7, - Relay = 8 + Relay = 8, + PWM = 9 }; static inline int16_t getHandleIndex(HalHandle handle) { diff --git a/wpilibc/athena/include/AnalogTriggerOutput.h b/wpilibc/athena/include/AnalogTriggerOutput.h index 024e3c84eb..bedf251303 100644 --- a/wpilibc/athena/include/AnalogTriggerOutput.h +++ b/wpilibc/athena/include/AnalogTriggerOutput.h @@ -52,6 +52,7 @@ class AnalogTriggerOutput : public DigitalSource { virtual uint32_t GetChannelForRouting() const override; virtual uint32_t GetModuleForRouting() const override; virtual bool GetAnalogTriggerForRouting() const override; + virtual HalHandle GetPortHandle() const override; protected: AnalogTriggerOutput(const AnalogTrigger& trigger, diff --git a/wpilibc/athena/include/DigitalInput.h b/wpilibc/athena/include/DigitalInput.h index 9e90242ce7..b488696deb 100644 --- a/wpilibc/athena/include/DigitalInput.h +++ b/wpilibc/athena/include/DigitalInput.h @@ -35,6 +35,7 @@ class DigitalInput : public DigitalSource, public LiveWindowSendable { virtual uint32_t GetChannelForRouting() const; virtual uint32_t GetModuleForRouting() const; virtual bool GetAnalogTriggerForRouting() const; + virtual HalHandle GetPortHandle() const; void UpdateTable(); void StartLiveWindowMode(); @@ -45,6 +46,7 @@ class DigitalInput : public DigitalSource, public LiveWindowSendable { private: uint32_t m_channel; + HalDigitalHandle m_handle; std::shared_ptr m_table; friend class DigitalGlitchFilter; diff --git a/wpilibc/athena/include/DigitalOutput.h b/wpilibc/athena/include/DigitalOutput.h index 82863477d7..643a79edc7 100644 --- a/wpilibc/athena/include/DigitalOutput.h +++ b/wpilibc/athena/include/DigitalOutput.h @@ -38,6 +38,7 @@ class DigitalOutput : public DigitalSource, virtual uint32_t GetChannelForRouting() const; virtual uint32_t GetModuleForRouting() const; virtual bool GetAnalogTriggerForRouting() const; + virtual HalHandle GetPortHandle() const; virtual void ValueChanged(ITable* source, llvm::StringRef key, std::shared_ptr value, bool isNew); @@ -50,6 +51,7 @@ class DigitalOutput : public DigitalSource, private: uint32_t m_channel; + HalDigitalHandle m_handle; void* m_pwmGenerator; std::shared_ptr m_table; diff --git a/wpilibc/athena/include/DigitalSource.h b/wpilibc/athena/include/DigitalSource.h index d85102b3c3..727a1372cc 100644 --- a/wpilibc/athena/include/DigitalSource.h +++ b/wpilibc/athena/include/DigitalSource.h @@ -7,6 +7,7 @@ #pragma once +#include "HAL/Handles.h" #include "InterruptableSensorBase.h" /** @@ -25,4 +26,5 @@ class DigitalSource : public InterruptableSensorBase { virtual uint32_t GetChannelForRouting() const = 0; virtual uint32_t GetModuleForRouting() const = 0; virtual bool GetAnalogTriggerForRouting() const = 0; + virtual HalHandle GetPortHandle() const = 0; }; diff --git a/wpilibc/athena/include/PWM.h b/wpilibc/athena/include/PWM.h index 33312dceeb..61a87f2560 100644 --- a/wpilibc/athena/include/PWM.h +++ b/wpilibc/athena/include/PWM.h @@ -9,6 +9,7 @@ #include +#include "HAL/Handles.h" #include "LiveWindow/LiveWindowSendable.h" #include "SensorBase.h" #include "tables/ITableListener.h" @@ -108,6 +109,7 @@ class PWM : public SensorBase, private: uint32_t m_channel; + HalDigitalHandle m_handle; int32_t GetMaxPositivePwm() const { return m_maxPwm; } int32_t GetMinPositivePwm() const { return m_eliminateDeadband ? m_deadbandMaxPwm : m_centerPwm + 1; diff --git a/wpilibc/athena/src/AnalogTriggerOutput.cpp b/wpilibc/athena/src/AnalogTriggerOutput.cpp index 791bf3f574..7b9a371a8f 100644 --- a/wpilibc/athena/src/AnalogTriggerOutput.cpp +++ b/wpilibc/athena/src/AnalogTriggerOutput.cpp @@ -66,3 +66,10 @@ uint32_t AnalogTriggerOutput::GetModuleForRouting() const { return 0; } * @return The value to be written to the module field of a routing mux. */ bool AnalogTriggerOutput::GetAnalogTriggerForRouting() const { return true; } + +/** + * @return The HAL Handle to the specified source. + */ +HalHandle AnalogTriggerOutput::GetPortHandle() const { + return m_trigger.m_trigger; +} diff --git a/wpilibc/athena/src/DigitalGlitchFilter.cpp b/wpilibc/athena/src/DigitalGlitchFilter.cpp index 39276270de..394f756511 100644 --- a/wpilibc/athena/src/DigitalGlitchFilter.cpp +++ b/wpilibc/athena/src/DigitalGlitchFilter.cpp @@ -53,14 +53,18 @@ void DigitalGlitchFilter::DoAdd(DigitalSource* input, int requested_index) { // Some sources from Counters and Encoders are null. By pushing the check // here, we catch the issue more generally. if (input) { + // we don't support GlitchFilters on AnalogTriggers. + if (input->GetAnalogTriggerForRouting()) { + wpi_setErrorWithContext( + -1, "Analog Triggers not supported for DigitalGlitchFilters"); + return; + } int32_t status = 0; - setFilterSelect(m_digital_ports[input->GetChannelForRouting()], - requested_index, &status); + setFilterSelect(input->GetPortHandle(), requested_index, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); // Validate that we set it correctly. - int actual_index = getFilterSelect( - m_digital_ports[input->GetChannelForRouting()], &status); + int actual_index = getFilterSelect(input->GetPortHandle(), &status); wpi_assertEqual(actual_index, requested_index); HALReport(HALUsageReporting::kResourceType_DigitalInput, diff --git a/wpilibc/athena/src/DigitalInput.cpp b/wpilibc/athena/src/DigitalInput.cpp index 9b2b15206c..25c48a581b 100644 --- a/wpilibc/athena/src/DigitalInput.cpp +++ b/wpilibc/athena/src/DigitalInput.cpp @@ -34,8 +34,13 @@ DigitalInput::DigitalInput(uint32_t channel) { m_channel = channel; int32_t status = 0; - allocateDIO(m_digital_ports[channel], true, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_handle = initializeDIOPort(getPort(channel), true, &status); + if (status != 0) { + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_handle = HAL_INVALID_HANDLE; + m_channel = std::numeric_limits::max(); + return; + } LiveWindow::GetInstance()->AddSensor("DigitalInput", channel, this); HALReport(HALUsageReporting::kResourceType_DigitalInput, channel); @@ -53,9 +58,7 @@ DigitalInput::~DigitalInput() { m_interrupt = HAL_INVALID_HANDLE; } - int32_t status = 0; - freeDIO(m_digital_ports[m_channel], &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); + freeDIOPort(m_handle); } /** @@ -66,7 +69,7 @@ DigitalInput::~DigitalInput() { bool DigitalInput::Get() const { if (StatusIsFatal()) return false; int32_t status = 0; - bool value = getDIO(m_digital_ports[m_channel], &status); + bool value = getDIO(m_handle, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); return value; } @@ -91,6 +94,11 @@ uint32_t DigitalInput::GetModuleForRouting() const { return 0; } */ bool DigitalInput::GetAnalogTriggerForRouting() const { return false; } +/** + * @return The HAL Handle to the specified source. + */ +HalHandle DigitalInput::GetPortHandle() const { return m_handle; } + void DigitalInput::UpdateTable() { if (m_table != nullptr) { m_table->PutBoolean("Value", Get()); diff --git a/wpilibc/athena/src/DigitalOutput.cpp b/wpilibc/athena/src/DigitalOutput.cpp index e72726f646..9bbf2012f9 100644 --- a/wpilibc/athena/src/DigitalOutput.cpp +++ b/wpilibc/athena/src/DigitalOutput.cpp @@ -35,8 +35,13 @@ DigitalOutput::DigitalOutput(uint32_t channel) { m_channel = channel; int32_t status = 0; - allocateDIO(m_digital_ports[channel], false, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_handle = initializeDIOPort(getPort(channel), false, &status); + if (status != 0) { + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_channel = std::numeric_limits::max(); + m_handle = HAL_INVALID_HANDLE; + return; + } HALReport(HALUsageReporting::kResourceType_DigitalOutput, channel); } @@ -50,9 +55,7 @@ DigitalOutput::~DigitalOutput() { // Disable the PWM in case it was running. DisablePWM(); - int32_t status = 0; - freeDIO(m_digital_ports[m_channel], &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); + freeDIOPort(m_handle); } /** @@ -66,7 +69,7 @@ void DigitalOutput::Set(uint32_t value) { if (StatusIsFatal()) return; int32_t status = 0; - setDIO(m_digital_ports[m_channel], value, &status); + setDIO(m_handle, value, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); } @@ -87,7 +90,7 @@ void DigitalOutput::Pulse(float length) { if (StatusIsFatal()) return; int32_t status = 0; - pulse(m_digital_ports[m_channel], length, &status); + pulse(m_handle, length, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); } @@ -100,7 +103,7 @@ bool DigitalOutput::IsPulsing() const { if (StatusIsFatal()) return false; int32_t status = 0; - bool value = isPulsing(m_digital_ports[m_channel], &status); + bool value = isPulsing(m_handle, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); return value; } @@ -206,6 +209,11 @@ uint32_t DigitalOutput::GetModuleForRouting() const { return 0; } */ bool DigitalOutput::GetAnalogTriggerForRouting() const { return false; } +/** + * @return The HAL Handle to the specified source. + */ +HalHandle DigitalOutput::GetPortHandle() const { return m_handle; } + void DigitalOutput::ValueChanged(ITable* source, llvm::StringRef key, std::shared_ptr value, bool isNew) { if (!value->IsBoolean()) return; diff --git a/wpilibc/athena/src/PWM.cpp b/wpilibc/athena/src/PWM.cpp index c0d607c651..19abbcbad0 100644 --- a/wpilibc/athena/src/PWM.cpp +++ b/wpilibc/athena/src/PWM.cpp @@ -39,12 +39,16 @@ PWM::PWM(uint32_t channel) { } int32_t status = 0; - allocatePWMChannel(m_pwm_ports[channel], &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_handle = initializePWMPort(getPort(channel), &status); + if (status != 0) { + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_channel = std::numeric_limits::max(); + m_handle = HAL_INVALID_HANDLE; + } m_channel = channel; - setPWM(m_pwm_ports[m_channel], kPwmDisabled, &status); + setPWM(m_handle, kPwmDisabled, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); m_eliminateDeadband = false; @@ -60,10 +64,10 @@ PWM::PWM(uint32_t channel) { PWM::~PWM() { int32_t status = 0; - setPWM(m_pwm_ports[m_channel], kPwmDisabled, &status); + setPWM(m_handle, kPwmDisabled, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); - freePWMChannel(m_pwm_ports[m_channel], &status); + freePWMPort(m_handle, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); if (m_table != nullptr) m_table->RemoveTableListener(this); @@ -278,7 +282,7 @@ void PWM::SetRaw(unsigned short value) { if (StatusIsFatal()) return; int32_t status = 0; - setPWM(m_pwm_ports[m_channel], value, &status); + setPWM(m_handle, value, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); } @@ -293,7 +297,7 @@ unsigned short PWM::GetRaw() const { if (StatusIsFatal()) return 0; int32_t status = 0; - unsigned short value = getPWM(m_pwm_ports[m_channel], &status); + unsigned short value = getPWM(m_handle, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); return value; @@ -311,16 +315,13 @@ void PWM::SetPeriodMultiplier(PeriodMultiplier mult) { switch (mult) { case kPeriodMultiplier_4X: - setPWMPeriodScale(m_pwm_ports[m_channel], 3, - &status); // Squelch 3 out of 4 outputs + setPWMPeriodScale(m_handle, 3, &status); // Squelch 3 out of 4 outputs break; case kPeriodMultiplier_2X: - setPWMPeriodScale(m_pwm_ports[m_channel], 1, - &status); // Squelch 1 out of 2 outputs + setPWMPeriodScale(m_handle, 1, &status); // Squelch 1 out of 2 outputs break; case kPeriodMultiplier_1X: - setPWMPeriodScale(m_pwm_ports[m_channel], 0, - &status); // Don't squelch any outputs + setPWMPeriodScale(m_handle, 0, &status); // Don't squelch any outputs break; default: wpi_assert(false); @@ -334,7 +335,7 @@ void PWM::SetZeroLatch() { int32_t status = 0; - latchPWMZero(m_pwm_ports[m_channel], &status); + latchPWMZero(m_handle, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); } diff --git a/wpilibc/athena/src/SensorBase.cpp b/wpilibc/athena/src/SensorBase.cpp index a1aee83cf7..71b2a835ea 100644 --- a/wpilibc/athena/src/SensorBase.cpp +++ b/wpilibc/athena/src/SensorBase.cpp @@ -20,31 +20,6 @@ const uint32_t SensorBase::kRelayChannels; const uint32_t SensorBase::kPDPChannels; const uint32_t SensorBase::kChassisSlots; -static bool portsInitialized = false; -void* SensorBase::m_digital_ports[kDigitalChannels]; -void* SensorBase::m_pwm_ports[kPwmChannels]; - -/** - * Creates an instance of the sensor base and gets an FPGA handle - */ -SensorBase::SensorBase() { - if (!portsInitialized) { - for (uint32_t i = 0; i < kDigitalChannels; i++) { - HalPortHandle port = getPort(i); - int32_t status = 0; - m_digital_ports[i] = initializeDigitalPort(port, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - } - - for (uint32_t i = 0; i < kPwmChannels; i++) { - HalPortHandle port = getPort(i); - int32_t status = 0; - m_pwm_ports[i] = initializeDigitalPort(port, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - } - } -} - /** * Check that the solenoid module number is valid. * diff --git a/wpilibc/shared/include/SensorBase.h b/wpilibc/shared/include/SensorBase.h index 07fc6bf67f..278888e0f6 100644 --- a/wpilibc/shared/include/SensorBase.h +++ b/wpilibc/shared/include/SensorBase.h @@ -19,7 +19,7 @@ */ class SensorBase : public ErrorBase { public: - SensorBase(); + SensorBase() = default; virtual ~SensorBase() = default; SensorBase(const SensorBase&) = delete; @@ -45,9 +45,4 @@ class SensorBase : public ErrorBase { static const uint32_t kRelayChannels = 8; static const uint32_t kPDPChannels = 16; static const uint32_t kChassisSlots = 8; - - protected: - static void* m_digital_ports[kDigitalChannels]; - static void* m_relay_ports[kRelayChannels]; - static void* m_pwm_ports[kPwmChannels]; }; diff --git a/wpilibc/sim/src/SensorBase.cpp b/wpilibc/sim/src/SensorBase.cpp index d2ee427d06..56c4093cc5 100644 --- a/wpilibc/sim/src/SensorBase.cpp +++ b/wpilibc/sim/src/SensorBase.cpp @@ -18,11 +18,6 @@ const uint32_t SensorBase::kRelayChannels; const uint32_t SensorBase::kPDPChannels; const uint32_t SensorBase::kChassisSlots; -/** - * Creates an instance of the sensor base and gets an FPGA handle - */ -SensorBase::SensorBase() {} - /** * Check that the solenoid module number is valid. * diff --git a/wpilibj/src/athena/cpp/lib/DIOJNI.cpp b/wpilibj/src/athena/cpp/lib/DIOJNI.cpp index 76b76825c3..c61426b06c 100644 --- a/wpilibj/src/athena/cpp/lib/DIOJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/DIOJNI.cpp @@ -28,78 +28,47 @@ extern "C" { /* * Class: edu_wpi_first_wpilibj_hal_DIOJNI - * Method: initializeDigitalPort - * Signature: (I)J; + * Method: initializeDIOPort + * Signature: (IZ)I; */ -JNIEXPORT jlong JNICALL -Java_edu_wpi_first_wpilibj_hal_DIOJNI_initializeDigitalPort( - JNIEnv *env, jclass, jint id) { - DIOJNI_LOG(logDEBUG) << "Calling DIOJNI initializeDigitalPort"; +JNIEXPORT jint JNICALL +Java_edu_wpi_first_wpilibj_hal_DIOJNI_initializeDIOPort( + JNIEnv *env, jclass, jint id, jboolean input) { + DIOJNI_LOG(logDEBUG) << "Calling DIOJNI initializeDIOPort"; DIOJNI_LOG(logDEBUG) << "Port Handle = " << (HalPortHandle)id; + DIOJNI_LOG(logDEBUG) << "Input = " << (jint)input; int32_t status = 0; - void *dio = initializeDigitalPort((HalPortHandle)id, &status); + auto dio = initializeDIOPort((HalPortHandle)id, (uint8_t)input, &status); DIOJNI_LOG(logDEBUG) << "Status = " << status; - DIOJNI_LOG(logDEBUG) << "DIO Ptr = " << dio; + DIOJNI_LOG(logDEBUG) << "DIO Handle = " << dio; CheckStatus(env, status); - return (jlong)dio; + return (jint)dio; } /* * Class: edu_wpi_first_wpilibj_hal_DIOJNI -* Method: freeDigitalPort -* Signature: (J)V; +* Method: freeDIOPort +* Signature: (I)V; */ -JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_freeDigitalPort( - JNIEnv *env, jclass, jlong id) { - DIOJNI_LOG(logDEBUG) << "Calling DIOJNI freeDigitalPort"; - DIOJNI_LOG(logDEBUG) << "Port Ptr = " << (void *)id; - freeDigitalPort((void *)id); -} - -/* - * Class: edu_wpi_first_wpilibj_hal_DIOJNI - * Method: allocateDIO - * Signature: (JZ)Z - */ -JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_allocateDIO( - JNIEnv *env, jclass, jlong id, jboolean value) { - DIOJNI_LOG(logDEBUG) << "Calling DIOJNI allocateDIO"; - DIOJNI_LOG(logDEBUG) << "Port Ptr = " << (void *)id; - int32_t status = 0; - jboolean returnValue = allocateDIO((void *)id, value, &status); - DIOJNI_LOG(logDEBUG) << "Status = " << status; - DIOJNI_LOG(logDEBUG) << "allocateDIOResult = " << (jint)returnValue; - CheckStatus(env, status); - return returnValue; -} - -/* - * Class: edu_wpi_first_wpilibj_hal_DIOJNI - * Method: freeDIO - * Signature: (J)V - */ -JNIEXPORT void JNICALL -Java_edu_wpi_first_wpilibj_hal_DIOJNI_freeDIO(JNIEnv *env, jclass, jlong id) { - DIOJNI_LOG(logDEBUG) << "Calling DIOJNI freeDIO"; - DIOJNI_LOG(logDEBUG) << "Port Ptr = " << (void *)id; - int32_t status = 0; - freeDIO((void *)id, &status); - DIOJNI_LOG(logDEBUG) << "Status = " << status; - CheckStatus(env, status); +JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_freeDIOPort( + JNIEnv *env, jclass, jint id) { + DIOJNI_LOG(logDEBUG) << "Calling DIOJNI freeDIOPort"; + DIOJNI_LOG(logDEBUG) << "Port Handle = " << (HalDigitalHandle)id; + freeDIOPort((HalDigitalHandle)id); } /* * Class: edu_wpi_first_wpilibj_hal_DIOJNI * Method: setDIO - * Signature: (JS)V + * Signature: (IS)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_setDIO( - JNIEnv *env, jclass, jlong id, jshort value) { + JNIEnv *env, jclass, jint id, jshort value) { // DIOJNI_LOG(logDEBUG) << "Calling DIOJNI setDIO"; - // DIOJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id; + // DIOJNI_LOG(logDEBUG) << "Port Handle = " << (HalDigitalHandle)id; // DIOJNI_LOG(logDEBUG) << "Value = " << value; int32_t status = 0; - setDIO((void *)id, value, &status); + setDIO((HalDigitalHandle)id, value, &status); // DIOJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -110,11 +79,11 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_setDIO( * Signature: (J)Z */ JNIEXPORT jboolean JNICALL -Java_edu_wpi_first_wpilibj_hal_DIOJNI_getDIO(JNIEnv *env, jclass, jlong id) { +Java_edu_wpi_first_wpilibj_hal_DIOJNI_getDIO(JNIEnv *env, jclass, jint id) { // DIOJNI_LOG(logDEBUG) << "Calling DIOJNI getDIO"; - // DIOJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id; + // DIOJNI_LOG(logDEBUG) << "Port Handle = " << (HalDigitalHandle)id; int32_t status = 0; - jboolean returnValue = getDIO((void *)id, &status); + jboolean returnValue = getDIO((HalDigitalHandle)id, &status); // DIOJNI_LOG(logDEBUG) << "Status = " << status; // DIOJNI_LOG(logDEBUG) << "getDIOResult = " << (jint)returnValue; CheckStatus(env, status); @@ -128,11 +97,11 @@ Java_edu_wpi_first_wpilibj_hal_DIOJNI_getDIO(JNIEnv *env, jclass, jlong id) { */ JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_getDIODirection( - JNIEnv *env, jclass, jlong id) { + JNIEnv *env, jclass, jint id) { DIOJNI_LOG(logDEBUG) << "Calling DIOJNI getDIODirection (RR upd)"; - // DIOJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id; + // DIOJNI_LOG(logDEBUG) << "Port Handle = " << (HalDigitalHandle)id; int32_t status = 0; - jboolean returnValue = getDIODirection((void *)id, &status); + jboolean returnValue = getDIODirection((HalDigitalHandle)id, &status); // DIOJNI_LOG(logDEBUG) << "Status = " << status; DIOJNI_LOG(logDEBUG) << "getDIODirectionResult = " << (jint)returnValue; CheckStatus(env, status); @@ -145,12 +114,12 @@ Java_edu_wpi_first_wpilibj_hal_DIOJNI_getDIODirection( * Signature: (JD)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_pulse( - JNIEnv *env, jclass, jlong id, jdouble value) { + JNIEnv *env, jclass, jint id, jdouble value) { DIOJNI_LOG(logDEBUG) << "Calling DIOJNI pulse (RR upd)"; - // DIOJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id; + // DIOJNI_LOG(logDEBUG) << "Port Handle = " << (HalDigitalHandle)id; // DIOJNI_LOG(logDEBUG) << "Value = " << value; int32_t status = 0; - pulse((void *)id, value, &status); + pulse((HalDigitalHandle)id, value, &status); DIOJNI_LOG(logDEBUG) << "Did it work? Status = " << status; CheckStatus(env, status); } @@ -161,11 +130,11 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_pulse( * Signature: (J)Z */ JNIEXPORT jboolean JNICALL -Java_edu_wpi_first_wpilibj_hal_DIOJNI_isPulsing(JNIEnv *env, jclass, jlong id) { +Java_edu_wpi_first_wpilibj_hal_DIOJNI_isPulsing(JNIEnv *env, jclass, jint id) { DIOJNI_LOG(logDEBUG) << "Calling DIOJNI isPulsing (RR upd)"; - // DIOJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id; + // DIOJNI_LOG(logDEBUG) << "Port Handle = " << (HalDigitalHandle)id; int32_t status = 0; - jboolean returnValue = isPulsing((void *)id, &status); + jboolean returnValue = isPulsing((HalDigitalHandle)id, &status); // DIOJNI_LOG(logDEBUG) << "Status = " << status; DIOJNI_LOG(logDEBUG) << "isPulsingResult = " << (jint)returnValue; CheckStatus(env, status); diff --git a/wpilibj/src/athena/cpp/lib/DigitalGlitchFilterJNI.cpp b/wpilibj/src/athena/cpp/lib/DigitalGlitchFilterJNI.cpp index 6e2bf0377e..975463e7a4 100644 --- a/wpilibj/src/athena/cpp/lib/DigitalGlitchFilterJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/DigitalGlitchFilterJNI.cpp @@ -17,11 +17,10 @@ */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_DigitalGlitchFilterJNI_setFilterSelect( - JNIEnv* env, jclass, jlong port_pointer, jint filter_index) { + JNIEnv* env, jclass, jint id, jint filter_index) { int32_t status = 0; - void* digital_port_pointer = reinterpret_cast(port_pointer); - setFilterSelect(digital_port_pointer, filter_index, &status); + setFilterSelect((HalDigitalHandle)id, filter_index, &status); CheckStatus(env, status); } @@ -31,11 +30,10 @@ Java_edu_wpi_first_wpilibj_hal_DigitalGlitchFilterJNI_setFilterSelect( */ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_DigitalGlitchFilterJNI_getFilterSelect( - JNIEnv* env, jclass, jlong port_pointer) { + JNIEnv* env, jclass, jint id) { int32_t status = 0; - void* digital_port_pointer = reinterpret_cast(port_pointer); - jint result = getFilterSelect(digital_port_pointer, &status); + jint result = getFilterSelect((HalDigitalHandle)id, &status); CheckStatus(env, status); return result; } diff --git a/wpilibj/src/athena/cpp/lib/PWMJNI.cpp b/wpilibj/src/athena/cpp/lib/PWMJNI.cpp index 6ca72e952b..9cb0316705 100644 --- a/wpilibj/src/athena/cpp/lib/PWMJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/PWMJNI.cpp @@ -28,48 +28,47 @@ extern "C" { /* * Class: edu_wpi_first_wpilibj_hal_PWMJNI - * Method: allocatePWMChannel - * Signature: (J)Z + * Method: initializePWMPort + * Signature: (I)I; */ -JNIEXPORT jboolean JNICALL -Java_edu_wpi_first_wpilibj_hal_PWMJNI_allocatePWMChannel( - JNIEnv* env, jclass, jlong id) { - PWMJNI_LOG(logDEBUG) << "Calling DIOJNI allocatePWMChannel"; - PWMJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id; +JNIEXPORT jint JNICALL +Java_edu_wpi_first_wpilibj_hal_PWMJNI_initializePWMPort( + JNIEnv *env, jclass, jint id) { + PWMJNI_LOG(logDEBUG) << "Calling PWMJNI initializePWMPort"; + PWMJNI_LOG(logDEBUG) << "Port Handle = " << (HalPortHandle)id; int32_t status = 0; - jboolean returnValue = allocatePWMChannel((void*)id, &status); + auto pwm = initializePWMPort((HalPortHandle)id, &status); PWMJNI_LOG(logDEBUG) << "Status = " << status; - PWMJNI_LOG(logDEBUG) << "allocatePWMChannelResult = " << (jint)returnValue; + PWMJNI_LOG(logDEBUG) << "PWM Handle = " << pwm; CheckStatus(env, status); - return returnValue; + return (jint)pwm; } /* - * Class: edu_wpi_first_wpilibj_hal_PWMJNI - * Method: freePWMChannel - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_PWMJNI_freePWMChannel( - JNIEnv* env, jclass, jlong id) { - PWMJNI_LOG(logDEBUG) << "Calling DIOJNI freePWMChannel"; - PWMJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id; +* Class: edu_wpi_first_wpilibj_hal_DIOJNI +* Method: freeDIOPort +* Signature: (I)V; +*/ +JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_PWMJNI_freePWMPort( + JNIEnv *env, jclass, jint id) { + PWMJNI_LOG(logDEBUG) << "Calling PWMJNI freePWMPort"; + PWMJNI_LOG(logDEBUG) << "Port Handle = " << (HalDigitalHandle)id; int32_t status = 0; - freePWMChannel((void*)id, &status); - PWMJNI_LOG(logDEBUG) << "Status = " << status; + freePWMPort((HalDigitalHandle)id, &status); CheckStatus(env, status); } /* * Class: edu_wpi_first_wpilibj_hal_PWMJNI * Method: setPWM - * Signature: (JS)V + * Signature: (IS)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_PWMJNI_setPWM( - JNIEnv* env, jclass, jlong id, jshort value) { - PWMJNI_LOG(logDEBUG) << "DigitalPort Ptr = " << (void*)id; + JNIEnv* env, jclass, jint id, jshort value) { + PWMJNI_LOG(logDEBUG) << "PWM Handle = " << (HalDigitalHandle)id; PWMJNI_LOG(logDEBUG) << "PWM Value = " << value; int32_t status = 0; - setPWM((void*)id, value, &status); + setPWM((HalDigitalHandle)id, value, &status); PWMJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -77,13 +76,13 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_PWMJNI_setPWM( /* * Class: edu_wpi_first_wpilibj_hal_PWMJNI * Method: getPWM - * Signature: (J)S + * Signature: (I)S */ JNIEXPORT jshort JNICALL -Java_edu_wpi_first_wpilibj_hal_PWMJNI_getPWM(JNIEnv* env, jclass, jlong id) { - PWMJNI_LOG(logDEBUG) << "PWM Ptr = " << (void*)id; +Java_edu_wpi_first_wpilibj_hal_PWMJNI_getPWM(JNIEnv* env, jclass, jint id) { + PWMJNI_LOG(logDEBUG) << "PWM Handle = " << (HalDigitalHandle)id; int32_t status = 0; - jshort returnValue = getPWM((void*)id, &status); + jshort returnValue = getPWM((HalDigitalHandle)id, &status); PWMJNI_LOG(logDEBUG) << "Status = " << status; PWMJNI_LOG(logDEBUG) << "Value = " << returnValue; CheckStatus(env, status); @@ -93,13 +92,13 @@ Java_edu_wpi_first_wpilibj_hal_PWMJNI_getPWM(JNIEnv* env, jclass, jlong id) { /* * Class: edu_wpi_first_wpilibj_hal_PWMJNI * Method: latchPWMZero - * Signature: (J)V + * Signature: (I)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_PWMJNI_latchPWMZero( - JNIEnv* env, jclass, jlong id) { - PWMJNI_LOG(logDEBUG) << "PWM Ptr = " << (void*)id; + JNIEnv* env, jclass, jint id) { + PWMJNI_LOG(logDEBUG) << "PWM Handle = " << (HalDigitalHandle)id; int32_t status = 0; - latchPWMZero((void*)id, &status); + latchPWMZero((HalDigitalHandle)id, &status); PWMJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -107,14 +106,14 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_PWMJNI_latchPWMZero( /* * Class: edu_wpi_first_wpilibj_hal_PWMJNI * Method: setPWMPeriodScale - * Signature: (JI)V + * Signature: (II)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_PWMJNI_setPWMPeriodScale( - JNIEnv* env, jclass, jlong id, jint value) { - PWMJNI_LOG(logDEBUG) << "DigitalPort Ptr = " << (void*)id; + JNIEnv* env, jclass, jint id, jint value) { + PWMJNI_LOG(logDEBUG) << "PWM Handle = " << (HalDigitalHandle)id; PWMJNI_LOG(logDEBUG) << "PeriodScale Value = " << value; int32_t status = 0; - setPWMPeriodScale((void*)id, value, &status); + setPWMPeriodScale((HalDigitalHandle)id, value, &status); PWMJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/AnalogTriggerOutput.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/AnalogTriggerOutput.java index 73a1b2684a..8a4b25804e 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/AnalogTriggerOutput.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/AnalogTriggerOutput.java @@ -80,10 +80,15 @@ public class AnalogTriggerOutput extends DigitalSource { UsageReporting.report(tResourceType.kResourceType_AnalogTriggerOutput, trigger.getIndex(), outputType.m_value); } - - @Override + + /** + * Frees the resources for this output. + */ public void free() { - + if (m_interrupt != 0) { + cancelInterrupts(); + } + } /** @@ -109,6 +114,11 @@ public class AnalogTriggerOutput extends DigitalSource { public boolean getAnalogTriggerForRouting() { return true; } + + @Override + public int getPortHandle() { + return m_trigger.m_port; + } /** * Defines the state in which the AnalogTrigger triggers. diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalGlitchFilter.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalGlitchFilter.java index 5113661e76..364c6f7cf1 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalGlitchFilter.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalGlitchFilter.java @@ -53,9 +53,13 @@ public class DigitalGlitchFilter extends SensorBase { private static void setFilter(DigitalSource input, int channelIndex) { if (input != null) { // Counter might have just one input - DigitalGlitchFilterJNI.setFilterSelect(input.m_port, channelIndex); + // analog triggers are not supported for DigitalGlitchFilters + if (input.getAnalogTriggerForRouting()) { + throw new IllegalStateException("Analog Triggers not supported for DigitalGlitchFilters"); + } + DigitalGlitchFilterJNI.setFilterSelect(input.getPortHandle(), channelIndex); - int selected = DigitalGlitchFilterJNI.getFilterSelect(input.m_port); + int selected = DigitalGlitchFilterJNI.getFilterSelect(input.getPortHandle()); if (selected != channelIndex) { throw new IllegalStateException("DigitalGlitchFilterJNI.setFilterSelect(" + channelIndex + ") failed -> " + selected); diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalInput.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalInput.java index c8cf32e1a6..1afba3e24a 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalInput.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalInput.java @@ -21,18 +21,34 @@ import edu.wpi.first.wpilibj.tables.ITable; * for devices like switches etc. that aren't implemented anywhere else. */ public class DigitalInput extends DigitalSource implements LiveWindowSendable { - + private int m_channel = 0; + private int m_handle = 0; + /** * Create an instance of a Digital Input class. Creates a digital input given a channel. * * @param channel the DIO channel for the digital input 0-9 are on-board, 10-25 are on the MXP */ public DigitalInput(int channel) { - initDigitalPort(channel, true); + checkDigitalChannel(channel); + m_channel = channel; + + m_handle = DIOJNI.initializeDIOPort(DIOJNI.getPort((byte)channel), true); LiveWindow.addSensor("DigitalInput", channel, this); UsageReporting.report(tResourceType.kResourceType_DigitalInput, channel); } + + /** + * Frees the resources for this output. + */ + public void free() { + if (m_interrupt != 0) { + cancelInterrupts(); + } + + DIOJNI.freeDIOPort(m_handle); + } /** * Get the value from a digital input channel. Retrieve the value of a single digital input @@ -41,7 +57,7 @@ public class DigitalInput extends DigitalSource implements LiveWindowSendable { * @return the status of the digital input */ public boolean get() { - return DIOJNI.getDIO(super.m_port); + return DIOJNI.getDIO(m_handle); } /** @@ -50,13 +66,48 @@ public class DigitalInput extends DigitalSource implements LiveWindowSendable { * @return The GPIO channel number that this object represents. */ public int getChannel() { - return super.m_channel; + return m_channel; } + /** + * Get the channel routing number. + * + * @return channel routing number + */ + @Override + public int getChannelForRouting() { + return m_channel; + } + + /** + * Get the module routing number. + * + * @return 0 + */ + @Override + public byte getModuleForRouting() { + return 0; + } + + /** + * Is this an analog trigger. + * + * @return true if this is an analog trigger + */ @Override public boolean getAnalogTriggerForRouting() { return false; } + + /** + * Get the HAL Port Handle. + * + * @return The HAL Handle to the specified source. + */ + @Override + public int getPortHandle() { + return m_handle; + } @Override diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalOutput.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalOutput.java index 5d584a2e6e..5c315d7b6e 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalOutput.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalOutput.java @@ -24,6 +24,9 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { private static final long invalidPwmGenerator = 0xffffffff; private long m_pwmGenerator = invalidPwmGenerator; + + private int m_channel = 0; + private int m_handle = 0; /** * Create an instance of a digital output. Create an instance of a digital output given a @@ -33,7 +36,10 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { * the MXP */ public DigitalOutput(int channel) { - initDigitalPort(channel, false); + checkDigitalChannel(channel); + m_channel = channel; + + m_handle = DIOJNI.initializeDIOPort(DIOJNI.getPort((byte)channel), false); UsageReporting.report(tResourceType.kResourceType_DigitalOutput, channel); } @@ -47,7 +53,8 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { if (m_pwmGenerator != invalidPwmGenerator) { disablePWM(); } - super.free(); + DIOJNI.freeDIOPort(m_handle); + m_handle = 0; } /** @@ -56,14 +63,14 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { * @param value true is on, off is false */ public void set(boolean value) { - DIOJNI.setDIO(super.m_port, (short) (value ? 1 : 0)); + DIOJNI.setDIO(m_handle, (short) (value ? 1 : 0)); } /** * @return The GPIO channel number that this object represents. */ public int getChannel() { - return super.m_channel; + return m_channel; } /** @@ -74,7 +81,7 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { * @param pulseLength The length of the pulse. */ public void pulse(final int channel, final float pulseLength) { - DIOJNI.pulse(super.m_port, pulseLength); + DIOJNI.pulse(m_handle, pulseLength); } /** @@ -89,7 +96,7 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { (float) (pulseLength / 1.0e9 * (DIOJNI.getLoopTiming() * 25)); System.err .println("You should use the float version of pulse for portability. This is deprecated"); - DIOJNI.pulse(super.m_port, convertedPulse); + DIOJNI.pulse(m_handle, convertedPulse); } /** @@ -98,7 +105,7 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { * @return true if pulsing */ public boolean isPulsing() { - return DIOJNI.isPulsing(super.m_port); + return DIOJNI.isPulsing(m_handle); } /** @@ -165,6 +172,46 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { } PWMJNI.setPWMDutyCycle(m_pwmGenerator, dutyCycle); } + + /** + * Get the channel routing number. + * + * @return channel routing number + */ + @Override + public int getChannelForRouting() { + return m_channel; + } + + /** + * Get the module routing number. + * + * @return 0 + */ + @Override + public byte getModuleForRouting() { + return 0; + } + + /** + * Is this an analog trigger. + * + * @return true if this is an analog trigger + */ + @Override + public boolean getAnalogTriggerForRouting() { + return false; + } + + /** + * Get the HAL Port Handle. + * + * @return The HAL Handle to the specified source. + */ + @Override + public int getPortHandle() { + return m_handle; + } /* * Live Window code, only does anything if live window is activated. diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalSource.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalSource.java index 3d18f75d0b..c4596145a0 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalSource.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalSource.java @@ -7,10 +7,6 @@ package edu.wpi.first.wpilibj; -import edu.wpi.first.wpilibj.hal.DIOJNI; -import edu.wpi.first.wpilibj.util.AllocationException; -import edu.wpi.first.wpilibj.util.CheckedAllocationException; - /** * DigitalSource Interface. The DigitalSource represents all the possible inputs for a counter or a * quadrature encoder. The source may be either a digital input or an analog input. If the caller @@ -18,64 +14,5 @@ import edu.wpi.first.wpilibj.util.CheckedAllocationException; * source. The source can either be a digital input or analog trigger but not both. */ public abstract class DigitalSource extends InterruptableSensorBase { - - protected static Resource channels = new Resource(kDigitalChannels); - protected long m_port; - protected int m_channel; - - protected void initDigitalPort(int channel, boolean input) { - - m_channel = channel; - - checkDigitalChannel(m_channel); - - try { - channels.allocate(m_channel); - } catch (CheckedAllocationException ex) { - throw new AllocationException("Digital input " + m_channel + " is already allocated"); - } - - int portHandle = DIOJNI.getPort((byte) channel); - m_port = DIOJNI.initializeDigitalPort(portHandle); - DIOJNI.allocateDIO(m_port, input); - } - - @Override - public void free() { - channels.free(m_channel); - DIOJNI.freeDIO(m_port); - DIOJNI.freeDigitalPort(m_port); - m_port = 0; - m_channel = 0; - } - - /** - * Get the channel routing number. - * - * @return channel routing number - */ - @Override - public int getChannelForRouting() { - return m_channel; - } - - /** - * Get the module routing number. - * - * @return 0 - */ - @Override - public byte getModuleForRouting() { - return 0; - } - - /** - * Is this an analog trigger. - * - * @return true if this is an analog trigger - */ - @Override - public boolean getAnalogTriggerForRouting() { - return false; - } + public abstract int getPortHandle(); } diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/PWM.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/PWM.java index 729741e816..bc0fe50594 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/PWM.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/PWM.java @@ -61,7 +61,7 @@ public class PWM extends SensorBase implements LiveWindowSendable { } private int m_channel; - private long m_port; + private int m_handle; /** * kDefaultPwmPeriod is in ms. @@ -106,13 +106,9 @@ public class PWM extends SensorBase implements LiveWindowSendable { checkPWMChannel(channel); m_channel = channel; - m_port = DIOJNI.initializeDigitalPort(DIOJNI.getPort((byte) channel)); + m_handle = PWMJNI.initializePWMPort(DIOJNI.getPort((byte) channel)); - if (!PWMJNI.allocatePWMChannel(m_port)) { - throw new AllocationException("PWM channel " + channel + " is already allocated"); - } - - PWMJNI.setPWM(m_port, (short) 0); + PWMJNI.setPWM(m_handle, (short) 0); m_eliminateDeadband = false; @@ -125,14 +121,12 @@ public class PWM extends SensorBase implements LiveWindowSendable { *

Free the resource associated with the PWM channel and set the value to 0. */ public void free() { - if (m_port == 0) { + if (m_handle == 0) { return; } - PWMJNI.setPWM(m_port, (short) 0); - PWMJNI.freePWMChannel(m_port); - PWMJNI.freeDIO(m_port); - DIOJNI.freeDigitalPort(m_port); - m_port = 0; + PWMJNI.setPWM(m_handle, (short) 0); + PWMJNI.freePWMPort(m_handle); + m_handle = 0; } /** @@ -320,7 +314,7 @@ public class PWM extends SensorBase implements LiveWindowSendable { * @param value Raw PWM value. Range 0 - 255. */ public void setRaw(int value) { - PWMJNI.setPWM(m_port, (short) value); + PWMJNI.setPWM(m_handle, (short) value); } /** @@ -331,7 +325,7 @@ public class PWM extends SensorBase implements LiveWindowSendable { * @return Raw PWM control value. Range: 0 - 255. */ public int getRaw() { - return PWMJNI.getPWM(m_port); + return PWMJNI.getPWM(m_handle); } /** @@ -343,15 +337,15 @@ public class PWM extends SensorBase implements LiveWindowSendable { switch (mult.value) { case PeriodMultiplier.k4X_val: // Squelch 3 out of 4 outputs - PWMJNI.setPWMPeriodScale(m_port, 3); + PWMJNI.setPWMPeriodScale(m_handle, 3); break; case PeriodMultiplier.k2X_val: // Squelch 1 out of 2 outputs - PWMJNI.setPWMPeriodScale(m_port, 1); + PWMJNI.setPWMPeriodScale(m_handle, 1); break; case PeriodMultiplier.k1X_val: // Don't squelch any outputs - PWMJNI.setPWMPeriodScale(m_port, 0); + PWMJNI.setPWMPeriodScale(m_handle, 0); break; default: // Cannot hit this, limited by PeriodMultiplier enum @@ -359,7 +353,7 @@ public class PWM extends SensorBase implements LiveWindowSendable { } protected void setZeroLatch() { - PWMJNI.latchPWMZero(m_port); + PWMJNI.latchPWMZero(m_handle); } private int getMaxPositivePwm() { diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Ultrasonic.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Ultrasonic.java index 85abc52fc1..8357c80518 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Ultrasonic.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Ultrasonic.java @@ -83,7 +83,7 @@ public class Ultrasonic extends SensorBase implements PIDSource, LiveWindowSenda return; } if (ultrasonic.isEnabled()) { - ultrasonic.m_pingChannel.pulse(m_pingChannel.m_channel, (float) kPingTime); // do + ultrasonic.m_pingChannel.pulse(m_pingChannel.getChannel(), (float) kPingTime); // do // the // ping } @@ -288,15 +288,8 @@ public class Ultrasonic extends SensorBase implements PIDSource, LiveWindowSenda setAutomaticMode(false); // turn off automatic round robin if pinging // single sensor m_counter.reset(); // reset the counter to zero (invalid data now) - m_pingChannel.pulse(m_pingChannel.m_channel, (float) kPingTime); // do - // the - // ping - // to - // start - // getting - // a - // single - // range + // do the ping to start getting a single range + m_pingChannel.pulse(m_pingChannel.getChannel(), (float) kPingTime); } /** diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/DIOJNI.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/DIOJNI.java index 54c558f500..c8eca75d94 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/DIOJNI.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/DIOJNI.java @@ -9,23 +9,19 @@ package edu.wpi.first.wpilibj.hal; @SuppressWarnings("AbbreviationAsWordInName") public class DIOJNI extends JNIWrapper { - public static native long initializeDigitalPort(int halPortHandle); + public static native int initializeDIOPort(int halPortHandle, boolean input); - public static native void freeDigitalPort(long portPointer); + public static native void freeDIOPort(int dioPortHandle); - public static native boolean allocateDIO(long digitalPortPointer, boolean input); + public static native void setDIO(int dioPortHandle, short value); - public static native void freeDIO(long digitalPortPointer); + public static native boolean getDIO(int dioPortHandle); - public static native void setDIO(long digitalPortPointer, short value); + public static native boolean getDIODirection(int dioPortHandle); - public static native boolean getDIO(long digitalPortPointer); + public static native void pulse(int dioPortHandle, double pulseLength); - public static native boolean getDIODirection(long digitalPortPointer); - - public static native void pulse(long digitalPortPointer, double pulseLength); - - public static native boolean isPulsing(long digitalPortPointer); + public static native boolean isPulsing(int dioPortHandle); public static native boolean isAnyPulsing(); diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/DigitalGlitchFilterJNI.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/DigitalGlitchFilterJNI.java index cf39a9537f..ec0b3a2e46 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/DigitalGlitchFilterJNI.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/DigitalGlitchFilterJNI.java @@ -8,9 +8,9 @@ package edu.wpi.first.wpilibj.hal; public class DigitalGlitchFilterJNI extends JNIWrapper { - public static native void setFilterSelect(long digitalPortPointer, int filterIndex); + public static native void setFilterSelect(int digitalPortHandle, int filterIndex); - public static native int getFilterSelect(long digitalPortPointer); + public static native int getFilterSelect(int digitalPortHandle); public static native void setFilterPeriod(int filterIndex, int fpgaCycles); diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/PWMJNI.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/PWMJNI.java index 50286599e2..64c0306402 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/PWMJNI.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/PWMJNI.java @@ -9,17 +9,17 @@ package edu.wpi.first.wpilibj.hal; @SuppressWarnings("AbbreviationAsWordInName") public class PWMJNI extends DIOJNI { - public static native boolean allocatePWMChannel(long digitalPortPointer); + public static native int initializePWMPort(int halPortHandle); - public static native void freePWMChannel(long digitalPortPointer); + public static native void freePWMPort(int pwmPortHandle); - public static native void setPWM(long digitalPortPointer, short value); + public static native void setPWM(int pwmPortHandle, short value); - public static native short getPWM(long digitalPortPointer); + public static native short getPWM(int pwmPortHandle); - public static native void latchPWMZero(long digitalPortPointer); + public static native void latchPWMZero(int pwmPortHandle); - public static native void setPWMPeriodScale(long digitalPortPointer, int squelchMask); + public static native void setPWMPeriodScale(int pwmPortHandle, int squelchMask); public static native long allocatePWM();