diff --git a/hal/include/HAL/Counter.h b/hal/include/HAL/Counter.h index f5212c9f82..8b84ae8d50 100644 --- a/hal/include/HAL/Counter.h +++ b/hal/include/HAL/Counter.h @@ -19,7 +19,7 @@ enum Mode { }; extern "C" { -HalCounterHandle initializeCounter(Mode mode, uint32_t* index, int32_t* status); +HalCounterHandle initializeCounter(Mode mode, int32_t* index, int32_t* status); void freeCounter(HalCounterHandle counter_handle, int32_t* status); void setCounterAverageSize(HalCounterHandle counter_handle, int32_t size, int32_t* status); diff --git a/hal/include/HAL/Encoder.h b/hal/include/HAL/Encoder.h index 1dd46fa2ee..f1d9d78026 100644 --- a/hal/include/HAL/Encoder.h +++ b/hal/include/HAL/Encoder.h @@ -9,26 +9,57 @@ #include +#include "HAL/Handles.h" + extern "C" { -void* initializeEncoder(uint8_t port_a_module, uint32_t port_a_pin, - bool port_a_analog_trigger, uint8_t port_b_module, - uint32_t port_b_pin, bool port_b_analog_trigger, - bool reverseDirection, int32_t* index, - int32_t* status); // TODO: fix routing -void freeEncoder(void* encoder_pointer, int32_t* status); -void resetEncoder(void* encoder_pointer, int32_t* status); -int32_t getEncoder(void* encoder_pointer, int32_t* status); // Raw value -double getEncoderPeriod(void* encoder_pointer, int32_t* status); -void setEncoderMaxPeriod(void* encoder_pointer, double maxPeriod, - int32_t* status); -bool getEncoderStopped(void* encoder_pointer, int32_t* status); -bool getEncoderDirection(void* encoder_pointer, int32_t* status); -void setEncoderReverseDirection(void* encoder_pointer, bool reverseDirection, +enum EncoderIndexingType { + HAL_kResetWhileHigh, + HAL_kResetWhileLow, + HAL_kResetOnFallingEdge, + HAL_kResetOnRisingEdge +}; +enum EncoderEncodingType { HAL_Encoder_k1X, HAL_Encoder_k2X, HAL_Encoder_k4X }; + +HalEncoderHandle initializeEncoder( + uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger, + uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger, + bool reverseDirection, EncoderEncodingType encodingType, int32_t* status); +void freeEncoder(HalEncoderHandle encoder_handle, int32_t* status); +int32_t getEncoder(HalEncoderHandle encoder_handle, int32_t* status); +int32_t getEncoderRaw(HalEncoderHandle encoder_handle, int32_t* status); +int32_t getEncoderEncodingScale(HalEncoderHandle encoder_handle, int32_t* status); -void setEncoderSamplesToAverage(void* encoder_pointer, - uint32_t samplesToAverage, int32_t* status); -uint32_t getEncoderSamplesToAverage(void* encoder_pointer, int32_t* status); -void setEncoderIndexSource(void* encoder_pointer, uint32_t pin, - bool analogTrigger, bool activeHigh, - bool edgeSensitive, int32_t* status); +void resetEncoder(HalEncoderHandle encoder_handle, int32_t* status); +int32_t getEncoderPeriod(HalEncoderHandle encoder_handle, int32_t* status); +void setEncoderMaxPeriod(HalEncoderHandle encoder_handle, double maxPeriod, + int32_t* status); +uint8_t getEncoderStopped(HalEncoderHandle encoder_handle, int32_t* status); +uint8_t getEncoderDirection(HalEncoderHandle encoder_handle, int32_t* status); +double getEncoderDistance(HalEncoderHandle encoder_handle, int32_t* status); +double getEncoderRate(HalEncoderHandle encoder_handle, int32_t* status); +void setEncoderMinRate(HalEncoderHandle encoder_handle, double minRate, + int32_t* status); +void setEncoderDistancePerPulse(HalEncoderHandle encoder_handle, + double distancePerPulse, int32_t* status); +void setEncoderReverseDirection(HalEncoderHandle encoder_handle, + uint8_t reverseDirection, int32_t* status); +void setEncoderSamplesToAverage(HalEncoderHandle encoder_handle, + int32_t samplesToAverage, int32_t* status); +int32_t getEncoderSamplesToAverage(HalEncoderHandle encoder_handle, + int32_t* status); + +void setEncoderIndexSource(HalEncoderHandle encoder_handle, uint32_t pin, + uint8_t analogTrigger, EncoderIndexingType type, + int32_t* status); + +int32_t getEncoderFPGAIndex(HalEncoderHandle encoder_handle, int32_t* status); + +double getEncoderDecodingScaleFactor(HalEncoderHandle encoder_handle, + int32_t* status); + +double getEncoderDistancePerPulse(HalEncoderHandle encoder_handle, + int32_t* status); + +EncoderEncodingType getEncoderEncodingType(HalEncoderHandle encoder_handle, + int32_t* status); } diff --git a/hal/include/HAL/Errors.h b/hal/include/HAL/Errors.h index de8e486b66..7fc1625f2f 100644 --- a/hal/include/HAL/Errors.h +++ b/hal/include/HAL/Errors.h @@ -67,6 +67,9 @@ #define PARAMETER_OUT_OF_RANGE_MESSAGE "HAL: A parameter is out of range." #define RESOURCE_IS_ALLOCATED -1029 #define RESOURCE_IS_ALLOCATED_MESSAGE "HAL: Resource already allocated" +#define HAL_COUNTER_NOT_SUPPORTED -1058 +#define HAL_COUNTER_NOT_SUPPORTED_MESSAGE \ + "HAL: Counter mode not supported for encoder method" #define VI_ERROR_SYSTEM_ERROR_MESSAGE "HAL - VISA: System Error"; #define VI_ERROR_INV_OBJECT_MESSAGE "HAL - VISA: Invalid Object" diff --git a/hal/include/HAL/HAL.h b/hal/include/HAL/HAL.h index e8a26d71da..11dd48f58b 100644 --- a/hal/include/HAL/HAL.h +++ b/hal/include/HAL/HAL.h @@ -17,7 +17,6 @@ #include "Compressor.h" #include "Counter.h" #include "DIO.h" -#include "Encoder.h" #include "Errors.h" #include "FRC_NetworkCommunication/UsageReporting.h" #include "Handles.h" diff --git a/hal/include/HAL/Handles.h b/hal/include/HAL/Handles.h index 1466cc5974..e01508837a 100644 --- a/hal/include/HAL/Handles.h +++ b/hal/include/HAL/Handles.h @@ -36,3 +36,7 @@ typedef HalHandle HalCounterHandle; typedef HalHandle HalCompressorHandle; typedef HalHandle HalSolenoidHandle; + +typedef HalHandle HalFPGAEncoderHandle; + +typedef HalHandle HalEncoderHandle; diff --git a/hal/lib/athena/Counter.cpp b/hal/lib/athena/Counter.cpp index 266df4a9aa..6d0648927f 100644 --- a/hal/lib/athena/Counter.cpp +++ b/hal/lib/athena/Counter.cpp @@ -26,8 +26,7 @@ static LimitedHandleResourceindex = quadEncoders->Allocate("4X Encoder"); - *index = encoder->index; - // TODO: if (index == ~0ul) { CloneError(quadEncoders); return; } - encoder->encoder = tEncoder::create(encoder->index, status); - encoder->encoder->writeConfig_ASource_Module(port_a_module, status); - encoder->encoder->writeConfig_ASource_Channel(port_a_pin, status); - encoder->encoder->writeConfig_ASource_AnalogTrigger(port_a_analog_trigger, - status); - encoder->encoder->writeConfig_BSource_Module(port_b_module, status); - encoder->encoder->writeConfig_BSource_Channel(port_b_pin, status); - encoder->encoder->writeConfig_BSource_AnalogTrigger(port_b_analog_trigger, - status); - encoder->encoder->strobeReset(status); - encoder->encoder->writeConfig_Reverse(reverseDirection, status); - encoder->encoder->writeTimerConfig_AverageSize(4, status); - - return encoder; -} - -void freeEncoder(void* encoder_pointer, int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - if (!encoder) return; - quadEncoders->Free(encoder->index); - delete encoder->encoder; -} - -/** - * Reset the Encoder distance to zero. - * Resets the current count to zero on the encoder. - */ -void resetEncoder(void* encoder_pointer, int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - encoder->encoder->strobeReset(status); -} - -/** - * Gets the raw value from the encoder. - * The raw value is the actual count unscaled by the 1x, 2x, or 4x scale - * factor. - * @return Current raw count from the encoder - */ -int32_t getEncoder(void* encoder_pointer, int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - return encoder->encoder->readOutput_Value(status); -} - -/** - * Returns the period of the most recent pulse. - * Returns the period of the most recent Encoder pulse in seconds. - * This method compenstates for the decoding type. - * - * @deprecated Use GetRate() in favor of this method. This returns unscaled - * periods and GetRate() scales using value from SetDistancePerPulse(). - * - * @return Period in seconds of the most recent pulse. - */ -double getEncoderPeriod(void* encoder_pointer, int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - tEncoder::tTimerOutput output = encoder->encoder->readTimerOutput(status); - double value; - if (output.Stalled) { - // Return infinity - double zero = 0.0; - value = 1.0 / zero; - } else { - // output.Period is a fixed point number that counts by 2 (24 bits, 25 - // integer bits) - value = (double)(output.Period << 1) / (double)output.Count; + m_encodingScale = encodingType == HAL_Encoder_k1X ? 1 : 2; + break; + } + default: + *status = PARAMETER_OUT_OF_RANGE; + return; } - double measuredPeriod = value * 2.5e-8; - return measuredPeriod / DECODING_SCALING_FACTOR; } -/** - * Sets the maximum period for stopped detection. - * Sets the value that represents the maximum period of the Encoder before it - * will assume that the attached device is stopped. This timeout allows users - * to determine if the wheels or other shaft has stopped rotating. - * This method compensates for the decoding type. - * - * @deprecated Use SetMinRate() in favor of this method. This takes unscaled - * periods and SetMinRate() scales using value from SetDistancePerPulse(). - * - * @param maxPeriod The maximum time between rising and falling edges before the - * FPGA will - * report the device stopped. This is expressed in seconds. - */ -void setEncoderMaxPeriod(void* encoder_pointer, double maxPeriod, - int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - encoder->encoder->writeTimerConfig_StallPeriod( - (uint32_t)(maxPeriod * 4.0e8 * DECODING_SCALING_FACTOR), status); +void Encoder::SetupCounter(uint8_t port_a_module, uint32_t port_a_pin, + bool port_a_analog_trigger, uint8_t port_b_module, + uint32_t port_b_pin, bool port_b_analog_trigger, + bool reverseDirection, + EncoderEncodingType encodingType, int32_t* status) { + m_encodingScale = encodingType == HAL_Encoder_k1X ? 1 : 2; + m_counter = initializeCounter(kExternalDirection, &m_index, status); + if (*status != 0) return; + setCounterMaxPeriod(m_counter, 0.5, status); + if (*status != 0) return; + setCounterUpSource(m_counter, port_a_pin, port_a_analog_trigger, status); + if (*status != 0) return; + setCounterDownSource(m_counter, port_b_pin, port_b_analog_trigger, status); + if (*status != 0) return; + if (encodingType == HAL_Encoder_k1X) { + setCounterUpSourceEdge(m_counter, true, false, status); + setCounterAverageSize(m_counter, 1, status); + } else { + setCounterUpSourceEdge(m_counter, true, true, status); + setCounterAverageSize(m_counter, 2, status); + } + setCounterDownSourceEdge(m_counter, reverseDirection, true, status); } -/** - * Determine if the encoder is stopped. - * Using the MaxPeriod value, a boolean is returned that is true if the encoder - * is considered stopped and false if it is still moving. A stopped encoder is - * one where the most recent pulse width exceeds the MaxPeriod. - * @return True if the encoder is considered stopped. - */ -bool getEncoderStopped(void* encoder_pointer, int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - return encoder->encoder->readTimerOutput_Stalled(status) != 0; +Encoder::~Encoder() { + if (m_counter != HAL_INVALID_HANDLE) { + int32_t status = 0; + freeCounter(m_counter, &status); + } else { + int32_t status = 0; + freeFPGAEncoder(m_encoder, &status); + } } -/** - * The last direction the encoder value changed. - * @return The last direction the encoder value changed. - */ -bool getEncoderDirection(void* encoder_pointer, int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - return encoder->encoder->readOutput_Direction(status); +// CounterBase interface +int32_t Encoder::Get(int32_t* status) const { + return (int32_t)(GetRaw(status) * DecodingScaleFactor()); } -/** - * Set the direction sensing for this encoder. - * This sets the direction sensing on the encoder so that it could count in the - * correct software direction regardless of the mounting. - * @param reverseDirection true if the encoder direction should be reversed - */ -void setEncoderReverseDirection(void* encoder_pointer, bool reverseDirection, - int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - encoder->encoder->writeConfig_Reverse(reverseDirection, status); +int32_t Encoder::GetRaw(int32_t* status) const { + if (m_counter) { + return getCounter(m_counter, status); + } else { + return getFPGAEncoder(m_encoder, status); + } } -/** - * Set the Samples to Average which specifies the number of samples of the timer - * to average when calculating the period. Perform averaging to account for - * mechanical imperfections or as oversampling to increase resolution. - * @param samplesToAverage The number of samples to average from 1 to 127. - */ -void setEncoderSamplesToAverage(void* encoder_pointer, - uint32_t samplesToAverage, int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; +int32_t Encoder::GetEncodingScale(int32_t* status) const { + return m_encodingScale; +} + +void Encoder::Reset(int32_t* status) { + if (m_counter) { + resetCounter(m_counter, status); + } else { + resetFPGAEncoder(m_encoder, status); + } +} + +double Encoder::GetPeriod(int32_t* status) const { + if (m_counter) { + return getCounterPeriod(m_counter, status) / DecodingScaleFactor(); + } else { + return getFPGAEncoderPeriod(m_encoder, status); + } +} + +void Encoder::SetMaxPeriod(double maxPeriod, int32_t* status) { + if (m_counter) { + setCounterMaxPeriod(m_counter, maxPeriod, status); + } else { + setFPGAEncoderMaxPeriod(m_encoder, maxPeriod, status); + } +} + +bool Encoder::GetStopped(int32_t* status) const { + if (m_counter) { + return getCounterStopped(m_counter, status); + } else { + return getFPGAEncoderStopped(m_encoder, status); + } +} + +bool Encoder::GetDirection(int32_t* status) const { + if (m_counter) { + return getCounterDirection(m_counter, status); + } else { + return getFPGAEncoderDirection(m_encoder, status); + } +} + +double Encoder::GetDistance(int32_t* status) const { + return GetRaw(status) * DecodingScaleFactor() * m_distancePerPulse; +} + +double Encoder::GetRate(int32_t* status) const { + return m_distancePerPulse / GetPeriod(status); +} + +void Encoder::SetMinRate(double minRate, int32_t* status) { + SetMaxPeriod(m_distancePerPulse / minRate, status); +} + +void Encoder::SetDistancePerPulse(double distancePerPulse, int32_t* status) { + m_distancePerPulse = distancePerPulse; +} + +void Encoder::SetReverseDirection(bool reverseDirection, int32_t* status) { + if (m_counter) { + setCounterReverseDirection(m_counter, reverseDirection, status); + } else { + setFPGAEncoderReverseDirection(m_encoder, reverseDirection, status); + } +} + +void Encoder::SetSamplesToAverage(int samplesToAverage, int32_t* status) { if (samplesToAverage < 1 || samplesToAverage > 127) { *status = PARAMETER_OUT_OF_RANGE; + return; + } + if (m_counter) { + setCounterSamplesToAverage(m_counter, samplesToAverage, status); + } else { + setFPGAEncoderSamplesToAverage(m_encoder, samplesToAverage, status); } - encoder->encoder->writeTimerConfig_AverageSize(samplesToAverage, status); } -/** - * Get the Samples to Average which specifies the number of samples of the timer - * to average when calculating the period. Perform averaging to account for - * mechanical imperfections or as oversampling to increase resolution. - * @return SamplesToAverage The number of samples being averaged (from 1 to 127) - */ -uint32_t getEncoderSamplesToAverage(void* encoder_pointer, int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - return encoder->encoder->readTimerConfig_AverageSize(status); +int32_t Encoder::GetSamplesToAverage(int32_t* status) const { + if (m_counter) { + return getCounterSamplesToAverage(m_counter, status); + } else { + return getFPGAEncoderSamplesToAverage(m_encoder, status); + } } -/** - * Set an index source for an encoder, which is an input that resets the - * encoder's count. - */ -void setEncoderIndexSource(void* encoder_pointer, uint32_t pin, - bool analogTrigger, bool activeHigh, - bool edgeSensitive, int32_t* status) { - Encoder* encoder = (Encoder*)encoder_pointer; - encoder->encoder->writeConfig_IndexSource_Channel((unsigned char)pin, status); - encoder->encoder->writeConfig_IndexSource_Module((unsigned char)0, status); - encoder->encoder->writeConfig_IndexSource_AnalogTrigger(analogTrigger, - status); - encoder->encoder->writeConfig_IndexActiveHigh(activeHigh, status); - encoder->encoder->writeConfig_IndexEdgeSensitive(edgeSensitive, status); +void Encoder::SetIndexSource(uint32_t pin, bool analogTrigger, + EncoderIndexingType type, int32_t* status) { + if (m_counter) { + *status = HAL_COUNTER_NOT_SUPPORTED; + return; + } + bool activeHigh = + (type == HAL_kResetWhileHigh) || (type == HAL_kResetOnRisingEdge); + bool edgeSensitive = + (type == HAL_kResetOnFallingEdge) || (type == HAL_kResetOnRisingEdge); + setFPGAEncoderIndexSource(m_encoder, pin, analogTrigger, activeHigh, + edgeSensitive, status); +} + +double Encoder::DecodingScaleFactor() const { + switch (m_encodingType) { + case HAL_Encoder_k1X: + return 1.0; + case HAL_Encoder_k2X: + return 0.5; + case HAL_Encoder_k4X: + return 0.25; + default: + return 0.0; + } +} + +static LimitedClassedHandleResource< + HalEncoderHandle, Encoder, tEncoder::kNumSystems + tCounter::kNumSystems, + HalHandleEnum::Encoder> + encoderHandles; + +extern "C" { +HalEncoderHandle initializeEncoder( + uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger, + uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger, + bool reverseDirection, EncoderEncodingType encodingType, int32_t* status) { + auto encoder = std::make_shared( + port_a_module, port_a_pin, port_a_analog_trigger, port_b_module, + port_b_pin, port_b_analog_trigger, reverseDirection, encodingType, + status); + if (*status != 0) return HAL_INVALID_HANDLE; // return in creation error + auto handle = encoderHandles.Allocate(encoder); + if (handle == HAL_INVALID_HANDLE) { + *status = NO_AVAILABLE_RESOURCES; + return HAL_INVALID_HANDLE; + } + return handle; +} + +void freeEncoder(HalEncoderHandle encoder_handle, int32_t* status) { + encoderHandles.Free(encoder_handle); +} + +int32_t getEncoder(HalEncoderHandle encoder_handle, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->Get(status); +} + +int32_t getEncoderRaw(HalEncoderHandle encoder_handle, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetRaw(status); +} + +int32_t getEncoderEncodingScale(HalEncoderHandle encoder_handle, + int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetEncodingScale(status); +} + +void resetEncoder(HalEncoderHandle encoder_handle, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->Reset(status); +} + +int32_t getEncoderPeriod(HalEncoderHandle encoder_handle, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetPeriod(status); +} + +void setEncoderMaxPeriod(HalEncoderHandle encoder_handle, double maxPeriod, + int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->SetMaxPeriod(maxPeriod, status); +} + +uint8_t getEncoderStopped(HalEncoderHandle encoder_handle, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetStopped(status); +} + +uint8_t getEncoderDirection(HalEncoderHandle encoder_handle, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetDirection(status); +} + +double getEncoderDistance(HalEncoderHandle encoder_handle, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetDistance(status); +} + +double getEncoderRate(HalEncoderHandle encoder_handle, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetRate(status); +} + +void setEncoderMinRate(HalEncoderHandle encoder_handle, double minRate, + int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->SetMinRate(minRate, status); +} + +void setEncoderDistancePerPulse(HalEncoderHandle encoder_handle, + double distancePerPulse, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->SetDistancePerPulse(distancePerPulse, status); +} + +void setEncoderReverseDirection(HalEncoderHandle encoder_handle, + uint8_t reverseDirection, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->SetReverseDirection(reverseDirection, status); +} + +void setEncoderSamplesToAverage(HalEncoderHandle encoder_handle, + int32_t samplesToAverage, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->SetSamplesToAverage(samplesToAverage, status); +} + +int32_t getEncoderSamplesToAverage(HalEncoderHandle encoder_handle, + int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetSamplesToAverage(status); +} + +double getEncoderDecodingScaleFactor(HalEncoderHandle encoder_handle, + int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->DecodingScaleFactor(); +} + +double getEncoderDistancePerPulse(HalEncoderHandle encoder_handle, + int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetDistancePerPulse(); +} + +EncoderEncodingType getEncoderEncodingType(HalEncoderHandle encoder_handle, + int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return HAL_Encoder_k4X; // default to k4X + } + return encoder->GetEncodingType(); +} + +void setEncoderIndexSource(HalEncoderHandle encoder_handle, uint32_t pin, + uint8_t analogTrigger, EncoderIndexingType type, + int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->SetIndexSource(pin, analogTrigger, type, status); +} + +int32_t getEncoderFPGAIndex(HalEncoderHandle encoder_handle, int32_t* status) { + auto encoder = encoderHandles.Get(encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->GetFPGAIndex(); } } diff --git a/hal/lib/athena/EncoderInternal.h b/hal/lib/athena/EncoderInternal.h new file mode 100644 index 0000000000..8e6e82efe3 --- /dev/null +++ b/hal/lib/athena/EncoderInternal.h @@ -0,0 +1,74 @@ +/*----------------------------------------------------------------------------*/ +/* 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 "HAL/Encoder.h" + +namespace hal { +class Encoder { + public: + Encoder(uint8_t port_a_module, uint32_t port_a_pin, + bool port_a_analog_trigger, uint8_t port_b_module, + uint32_t port_b_pin, bool port_b_analog_trigger, + bool reverseDirection, EncoderEncodingType encodingType, + int32_t* status); + ~Encoder(); + + // CounterBase interface + int32_t Get(int32_t* status) const; + int32_t GetRaw(int32_t* status) const; + int32_t GetEncodingScale(int32_t* status) const; + void Reset(int32_t* status); + double GetPeriod(int32_t* status) const; + void SetMaxPeriod(double maxPeriod, int32_t* status); + bool GetStopped(int32_t* status) const; + bool GetDirection(int32_t* status) const; + + double GetDistance(int32_t* status) const; + double GetRate(int32_t* status) const; + void SetMinRate(double minRate, int32_t* status); + void SetDistancePerPulse(double distancePerPulse, int32_t* status); + void SetReverseDirection(bool reverseDirection, int32_t* status); + void SetSamplesToAverage(int samplesToAverage, int32_t* status); + int32_t GetSamplesToAverage(int32_t* status) const; + + void SetIndexSource(uint32_t pin, bool analogTrigger, + EncoderIndexingType type, int32_t* status); + + int32_t GetFPGAIndex() const { return m_index; } + + int32_t GetEncodingScale() const { return m_encodingScale; } + + double DecodingScaleFactor() const; + + double GetDistancePerPulse() const { return m_distancePerPulse; } + + EncoderEncodingType GetEncodingType() const { return m_encodingType; } + + private: + void SetupCounter(uint8_t port_a_module, uint32_t port_a_pin, + bool port_a_analog_trigger, uint8_t port_b_module, + uint32_t port_b_pin, bool port_b_analog_trigger, + bool reverseDirection, EncoderEncodingType encodingType, + int32_t* status); + + HalFPGAEncoderHandle m_encoder = HAL_INVALID_HANDLE; + + HalCounterHandle m_counter = HAL_INVALID_HANDLE; + + int32_t m_index = 0; + + double m_distancePerPulse = 1.0; + + EncoderEncodingType m_encodingType; + + int32_t m_encodingScale; +}; +} diff --git a/hal/lib/athena/FPGAEncoder.cpp b/hal/lib/athena/FPGAEncoder.cpp new file mode 100644 index 0000000000..7b568fc952 --- /dev/null +++ b/hal/lib/athena/FPGAEncoder.cpp @@ -0,0 +1,272 @@ +/*----------------------------------------------------------------------------*/ +/* 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. */ +/*----------------------------------------------------------------------------*/ + +#include "FPGAEncoder.h" + +#include "DigitalInternal.h" +#include "handles/LimitedHandleResource.h" + +static_assert(sizeof(uint32_t) <= sizeof(void*), + "This file shoves uint32_ts into pointers."); + +using namespace hal; + +namespace { +struct Encoder { + tEncoder* encoder; + uint32_t index; +}; +} + +static const double DECODING_SCALING_FACTOR = 0.25; + +static LimitedHandleResource + fpgaEncoderHandles; + +extern "C" { +HalFPGAEncoderHandle initializeFPGAEncoder( + uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger, + uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger, + bool reverseDirection, int32_t* index, int32_t* status) { + remapDigitalSource(port_a_analog_trigger, port_a_pin, port_a_module); + remapDigitalSource(port_b_analog_trigger, port_b_pin, port_b_module); + + auto handle = fpgaEncoderHandles.Allocate(); + if (handle == HAL_INVALID_HANDLE) { // out of resources + *status = NO_AVAILABLE_RESOURCES; + return HAL_INVALID_HANDLE; + } + + auto encoder = fpgaEncoderHandles.Get(handle); + if (encoder == nullptr) { // will only error on thread issue + *status = PARAMETER_OUT_OF_RANGE; + return HAL_INVALID_HANDLE; + } + + encoder->index = static_cast(getHandleIndex(handle)); + + *index = encoder->index; + // TODO: if (index == ~0ul) { CloneError(quadEncoders); return; } + encoder->encoder = tEncoder::create(encoder->index, status); + encoder->encoder->writeConfig_ASource_Module(port_a_module, status); + encoder->encoder->writeConfig_ASource_Channel(port_a_pin, status); + encoder->encoder->writeConfig_ASource_AnalogTrigger(port_a_analog_trigger, + status); + encoder->encoder->writeConfig_BSource_Module(port_b_module, status); + encoder->encoder->writeConfig_BSource_Channel(port_b_pin, status); + encoder->encoder->writeConfig_BSource_AnalogTrigger(port_b_analog_trigger, + status); + encoder->encoder->strobeReset(status); + encoder->encoder->writeConfig_Reverse(reverseDirection, status); + encoder->encoder->writeTimerConfig_AverageSize(4, status); + + return handle; +} + +void freeFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + fpgaEncoderHandles.Free(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + delete encoder->encoder; +} + +/** + * Reset the Encoder distance to zero. + * Resets the current count to zero on the encoder. + */ +void resetFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->encoder->strobeReset(status); +} + +/** + * Gets the fpga value from the encoder. + * The fpga value is the actual count unscaled by the 1x, 2x, or 4x scale + * factor. + * @return Current fpga count from the encoder + */ +int32_t getFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->encoder->readOutput_Value(status); +} + +/** + * Returns the period of the most recent pulse. + * Returns the period of the most recent Encoder pulse in seconds. + * This method compenstates for the decoding type. + * + * @deprecated Use GetRate() in favor of this method. This returns unscaled + * periods and GetRate() scales using value from SetDistancePerPulse(). + * + * @return Period in seconds of the most recent pulse. + */ +double getFPGAEncoderPeriod(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0.0; + } + tEncoder::tTimerOutput output = encoder->encoder->readTimerOutput(status); + double value; + if (output.Stalled) { + // Return infinity + double zero = 0.0; + value = 1.0 / zero; + } else { + // output.Period is a fixed point number that counts by 2 (24 bits, 25 + // integer bits) + value = (double)(output.Period << 1) / (double)output.Count; + } + double measuredPeriod = value * 2.5e-8; + return measuredPeriod / DECODING_SCALING_FACTOR; +} + +/** + * Sets the maximum period for stopped detection. + * Sets the value that represents the maximum period of the Encoder before it + * will assume that the attached device is stopped. This timeout allows users + * to determine if the wheels or other shaft has stopped rotating. + * This method compensates for the decoding type. + * + * @deprecated Use SetMinRate() in favor of this method. This takes unscaled + * periods and SetMinRate() scales using value from SetDistancePerPulse(). + * + * @param maxPeriod The maximum time between rising and falling edges before the + * FPGA will + * report the device stopped. This is expressed in seconds. + */ +void setFPGAEncoderMaxPeriod(HalFPGAEncoderHandle fpga_encoder_handle, + double maxPeriod, int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->encoder->writeTimerConfig_StallPeriod( + (uint32_t)(maxPeriod * 4.0e8 * DECODING_SCALING_FACTOR), status); +} + +/** + * Determine if the encoder is stopped. + * Using the MaxPeriod value, a boolean is returned that is true if the encoder + * is considered stopped and false if it is still moving. A stopped encoder is + * one where the most recent pulse width exceeds the MaxPeriod. + * @return True if the encoder is considered stopped. + */ +bool getFPGAEncoderStopped(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return false; + } + return encoder->encoder->readTimerOutput_Stalled(status) != 0; +} + +/** + * The last direction the encoder value changed. + * @return The last direction the encoder value changed. + */ +bool getFPGAEncoderDirection(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return false; + } + return encoder->encoder->readOutput_Direction(status); +} + +/** + * Set the direction sensing for this encoder. + * This sets the direction sensing on the encoder so that it could count in the + * correct software direction regardless of the mounting. + * @param reverseDirection true if the encoder direction should be reversed + */ +void setFPGAEncoderReverseDirection(HalFPGAEncoderHandle fpga_encoder_handle, + bool reverseDirection, int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->encoder->writeConfig_Reverse(reverseDirection, status); +} + +/** + * Set the Samples to Average which specifies the number of samples of the timer + * to average when calculating the period. Perform averaging to account for + * mechanical imperfections or as oversampling to increase resolution. + * @param samplesToAverage The number of samples to average from 1 to 127. + */ +void setFPGAEncoderSamplesToAverage(HalFPGAEncoderHandle fpga_encoder_handle, + uint32_t samplesToAverage, + int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + if (samplesToAverage < 1 || samplesToAverage > 127) { + *status = PARAMETER_OUT_OF_RANGE; + } + encoder->encoder->writeTimerConfig_AverageSize(samplesToAverage, status); +} + +/** + * Get the Samples to Average which specifies the number of samples of the timer + * to average when calculating the period. Perform averaging to account for + * mechanical imperfections or as oversampling to increase resolution. + * @return SamplesToAverage The number of samples being averaged (from 1 to 127) + */ +uint32_t getFPGAEncoderSamplesToAverage( + HalFPGAEncoderHandle fpga_encoder_handle, int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } + return encoder->encoder->readTimerConfig_AverageSize(status); +} + +/** + * Set an index source for an encoder, which is an input that resets the + * encoder's count. + */ +void setFPGAEncoderIndexSource(HalFPGAEncoderHandle fpga_encoder_handle, + uint32_t pin, bool analogTrigger, + bool activeHigh, bool edgeSensitive, + int32_t* status) { + auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle); + if (encoder == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } + encoder->encoder->writeConfig_IndexSource_Channel((unsigned char)pin, status); + encoder->encoder->writeConfig_IndexSource_Module((unsigned char)0, status); + encoder->encoder->writeConfig_IndexSource_AnalogTrigger(analogTrigger, + status); + encoder->encoder->writeConfig_IndexActiveHigh(activeHigh, status); + encoder->encoder->writeConfig_IndexEdgeSensitive(edgeSensitive, status); +} +} diff --git a/hal/lib/athena/FPGAEncoder.h b/hal/lib/athena/FPGAEncoder.h new file mode 100644 index 0000000000..173a0274cf --- /dev/null +++ b/hal/lib/athena/FPGAEncoder.h @@ -0,0 +1,43 @@ +/*----------------------------------------------------------------------------*/ +/* 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 "HAL/Handles.h" + +extern "C" { +HalFPGAEncoderHandle initializeFPGAEncoder( + uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger, + uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger, + bool reverseDirection, int32_t* index, + int32_t* status); // TODO: fix routing +void freeFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle, int32_t* status); +void resetFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status); +int32_t getFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status); // Raw value +double getFPGAEncoderPeriod(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status); +void setFPGAEncoderMaxPeriod(HalFPGAEncoderHandle fpga_encoder_handle, + double maxPeriod, int32_t* status); +bool getFPGAEncoderStopped(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status); +bool getFPGAEncoderDirection(HalFPGAEncoderHandle fpga_encoder_handle, + int32_t* status); +void setFPGAEncoderReverseDirection(HalFPGAEncoderHandle fpga_encoder_handle, + bool reverseDirection, int32_t* status); +void setFPGAEncoderSamplesToAverage(HalFPGAEncoderHandle fpga_encoder_handle, + uint32_t samplesToAverage, int32_t* status); +uint32_t getFPGAEncoderSamplesToAverage( + HalFPGAEncoderHandle fpga_encoder_handle, int32_t* status); +void setFPGAEncoderIndexSource(HalFPGAEncoderHandle fpga_encoder_handle, + uint32_t pin, bool analogTrigger, + bool activeHigh, bool edgeSensitive, + int32_t* status); +} diff --git a/hal/lib/athena/HALAthena.cpp b/hal/lib/athena/HALAthena.cpp index afa2d20844..6fca08d4aa 100644 --- a/hal/lib/athena/HALAthena.cpp +++ b/hal/lib/athena/HALAthena.cpp @@ -111,6 +111,8 @@ const char* getHALErrorMessage(int32_t code) { return ANALOG_TRIGGER_PULSE_OUTPUT_ERROR_MESSAGE; case PARAMETER_OUT_OF_RANGE: return PARAMETER_OUT_OF_RANGE_MESSAGE; + case HAL_COUNTER_NOT_SUPPORTED: + return HAL_COUNTER_NOT_SUPPORTED_MESSAGE; case ERR_CANSessionMux_InvalidBuffer: return ERR_CANSessionMux_InvalidBuffer_MESSAGE; case ERR_CANSessionMux_MessageNotFound: diff --git a/hal/lib/athena/handles/HandlesInternal.h b/hal/lib/athena/handles/HandlesInternal.h index 46539f519c..37a48984a6 100644 --- a/hal/lib/athena/handles/HandlesInternal.h +++ b/hal/lib/athena/handles/HandlesInternal.h @@ -38,6 +38,8 @@ enum class HalHandleEnum { PWM = 9, DigitalPWM = 10, Counter = 11, + FPGAEncoder = 12, + Encoder = 13, Compressor = 14, Solenoid = 15 }; diff --git a/hal/lib/athena/handles/LimitedClassedHandleResource.h b/hal/lib/athena/handles/LimitedClassedHandleResource.h new file mode 100644 index 0000000000..2b8086f649 --- /dev/null +++ b/hal/lib/athena/handles/LimitedClassedHandleResource.h @@ -0,0 +1,99 @@ +/*----------------------------------------------------------------------------*/ +/* 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/Handles.h" +#include "HAL/cpp/priority_mutex.h" +#include "HandlesInternal.h" + +namespace hal { + +/** + * The LimitedClassedHandleResource class is a way to track handles. This + * version + * allows a limited number of handles that are allocated sequentially. + * + * @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 + * @tparam enumValue The type value stored in the handle + * + */ +template +class LimitedClassedHandleResource { + friend class LimitedClassedHandleResourceTest; + + public: + LimitedClassedHandleResource(const LimitedClassedHandleResource&) = delete; + LimitedClassedHandleResource operator=(const LimitedClassedHandleResource&) = + delete; + LimitedClassedHandleResource() = default; + THandle Allocate(std::shared_ptr toSet); + std::shared_ptr Get(THandle handle); + void Free(THandle handle); + + private: + std::shared_ptr m_structures[size]; + priority_mutex m_handleMutexes[size]; + priority_mutex m_allocateMutex; +}; + +template +THandle +LimitedClassedHandleResource::Allocate( + std::shared_ptr toSet) { + // globally lock to loop through indices + std::lock_guard sync(m_allocateMutex); + int16_t i; + for (i = 0; i < size; i++) { + if (m_structures[i] == nullptr) { + // if a false index is found, grab its specific mutex + // and allocate it. + std::lock_guard sync(m_handleMutexes[i]); + m_structures[i] = toSet; + return (THandle)createHandle(i, enumValue); + } + } + return HAL_INVALID_HANDLE; +} + +template +std::shared_ptr LimitedClassedHandleResource< + THandle, TStruct, size, enumValue>::Get(THandle handle) { + // 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 LimitedClassedHandleResource::Free( + THandle handle) { + // 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_allocateMutex); + std::lock_guard lock(m_handleMutexes[index]); + m_structures[index].reset(); +} +} diff --git a/wpilibc/athena/include/Counter.h b/wpilibc/athena/include/Counter.h index b3258e3d22..1141df30ea 100644 --- a/wpilibc/athena/include/Counter.h +++ b/wpilibc/athena/include/Counter.h @@ -83,7 +83,7 @@ class Counter : public SensorBase, void SetSamplesToAverage(int samplesToAverage); int GetSamplesToAverage() const; - uint32_t GetFPGAIndex() const { return m_index; } + int32_t GetFPGAIndex() const { return m_index; } void UpdateTable() override; void StartLiveWindowMode() override; @@ -101,7 +101,7 @@ class Counter : public SensorBase, HalCounterHandle m_counter = HAL_INVALID_HANDLE; private: - uint32_t m_index = 0; // The index of this counter. + int32_t m_index = 0; ///< The index of this counter. std::shared_ptr m_table; friend class DigitalGlitchFilter; diff --git a/wpilibc/athena/include/Encoder.h b/wpilibc/athena/include/Encoder.h index 05eae51525..8355455840 100644 --- a/wpilibc/athena/include/Encoder.h +++ b/wpilibc/athena/include/Encoder.h @@ -11,6 +11,7 @@ #include "Counter.h" #include "CounterBase.h" +#include "HAL/Encoder.h" #include "LiveWindow/LiveWindowSendable.h" #include "PIDSource.h" #include "SensorBase.h" @@ -88,21 +89,16 @@ class Encoder : public SensorBase, void InitTable(std::shared_ptr subTable) override; std::shared_ptr GetTable() const override; - int32_t GetFPGAIndex() const { return m_index; } + int32_t GetFPGAIndex() const; private: - void InitEncoder(bool _reverseDirection, EncodingType encodingType); + void InitEncoder(bool reverseDirection, EncodingType encodingType); + double DecodingScaleFactor() const; std::shared_ptr m_aSource; // the A phase of the quad encoder std::shared_ptr m_bSource; // the B phase of the quad encoder - void* m_encoder = nullptr; - int32_t m_index = 0; // The encoder's FPGA index. - double m_distancePerPulse = 1.0; // distance of travel for each encoder tick - std::unique_ptr m_counter = - nullptr; // Counter object for 1x and 2x encoding - EncodingType m_encodingType; // Encoding type - int32_t m_encodingScale; // 1x, 2x, or 4x, per the encodingType + HalEncoderHandle m_encoder = HAL_INVALID_HANDLE; std::shared_ptr m_table; friend class DigitalGlitchFilter; diff --git a/wpilibc/athena/src/Encoder.cpp b/wpilibc/athena/src/Encoder.cpp index 597c63ae88..79392cb17c 100644 --- a/wpilibc/athena/src/Encoder.cpp +++ b/wpilibc/athena/src/Encoder.cpp @@ -31,44 +31,17 @@ * be double (2x) the spec'd count. */ void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType) { - m_encodingType = encodingType; - switch (encodingType) { - case k4X: { - m_encodingScale = 4; - if (m_aSource->StatusIsFatal()) { - CloneError(*m_aSource); - return; - } - if (m_bSource->StatusIsFatal()) { - CloneError(*m_bSource); - return; - } - int32_t status = 0; - m_encoder = initializeEncoder( - m_aSource->GetModuleForRouting(), m_aSource->GetChannelForRouting(), - m_aSource->GetAnalogTriggerForRouting(), - m_bSource->GetModuleForRouting(), m_bSource->GetChannelForRouting(), - m_bSource->GetAnalogTriggerForRouting(), reverseDirection, &m_index, - &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - m_counter = nullptr; - SetMaxPeriod(.5); - break; - } - case k1X: - case k2X: { - m_encodingScale = encodingType == k1X ? 1 : 2; - m_counter = std::make_unique(m_encodingType, m_aSource, - m_bSource, reverseDirection); - m_index = m_counter->GetFPGAIndex(); - break; - } - default: - wpi_setErrorWithContext(-1, "Invalid encodingType argument"); - break; - } + int32_t status = 0; + m_encoder = initializeEncoder( + m_aSource->GetModuleForRouting(), m_aSource->GetChannelForRouting(), + m_aSource->GetAnalogTriggerForRouting(), m_bSource->GetModuleForRouting(), + m_bSource->GetChannelForRouting(), + m_bSource->GetAnalogTriggerForRouting(), reverseDirection, + (EncoderEncodingType)encodingType, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); - HALReport(HALUsageReporting::kResourceType_Encoder, m_index, encodingType); + HALReport(HALUsageReporting::kResourceType_Encoder, GetFPGAIndex(), + encodingType); LiveWindow::GetInstance()->AddSensor("Encoder", m_aSource->GetChannelForRouting(), this); } @@ -182,11 +155,9 @@ Encoder::Encoder(DigitalSource& aSource, DigitalSource& bSource, * Frees the FPGA resources associated with an Encoder. */ Encoder::~Encoder() { - if (!m_counter) { - int32_t status = 0; - freeEncoder(m_encoder, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - } + int32_t status = 0; + freeEncoder(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); } /** @@ -194,7 +165,12 @@ Encoder::~Encoder() { * * Used to divide raw edge counts down to spec'd counts. */ -int32_t Encoder::GetEncodingScale() const { return m_encodingScale; } +int32_t Encoder::GetEncodingScale() const { + int32_t status = 0; + int32_t val = getEncoderEncodingScale(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return val; +} /** * Gets the raw value from the encoder. @@ -206,14 +182,9 @@ int32_t Encoder::GetEncodingScale() const { return m_encodingScale; } */ int32_t Encoder::GetRaw() const { if (StatusIsFatal()) return 0; - int32_t value; - if (m_counter) - value = m_counter->Get(); - else { - int32_t status = 0; - value = getEncoder(m_encoder, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - } + int32_t status = 0; + int32_t value = getEncoderRaw(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); return value; } @@ -228,7 +199,10 @@ int32_t Encoder::GetRaw() const { */ int32_t Encoder::Get() const { if (StatusIsFatal()) return 0; - return (int32_t)(GetRaw() * DecodingScaleFactor()); + int32_t status = 0; + int32_t value = getEncoder(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return value; } /** @@ -238,13 +212,10 @@ int32_t Encoder::Get() const { */ void Encoder::Reset() { if (StatusIsFatal()) return; - if (m_counter) - m_counter->Reset(); - else { - int32_t status = 0; - resetEncoder(m_encoder, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - } + int32_t status = 0; + resetEncoder(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + ; } /** @@ -261,14 +232,10 @@ void Encoder::Reset() { */ double Encoder::GetPeriod() const { if (StatusIsFatal()) return 0.0; - if (m_counter) { - return m_counter->GetPeriod() / DecodingScaleFactor(); - } else { - int32_t status = 0; - double period = getEncoderPeriod(m_encoder, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - return period; - } + int32_t status = 0; + double value = getEncoderPeriod(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return value; } /** @@ -289,13 +256,9 @@ double Encoder::GetPeriod() const { */ void Encoder::SetMaxPeriod(double maxPeriod) { if (StatusIsFatal()) return; - if (m_counter) { - m_counter->SetMaxPeriod(maxPeriod * DecodingScaleFactor()); - } else { - int32_t status = 0; - setEncoderMaxPeriod(m_encoder, maxPeriod, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - } + int32_t status = 0; + setEncoderMaxPeriod(m_encoder, maxPeriod, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); } /** @@ -309,14 +272,10 @@ void Encoder::SetMaxPeriod(double maxPeriod) { */ bool Encoder::GetStopped() const { if (StatusIsFatal()) return true; - if (m_counter) { - return m_counter->GetStopped(); - } else { - int32_t status = 0; - bool value = getEncoderStopped(m_encoder, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - return value; - } + int32_t status = 0; + bool value = getEncoderStopped(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return value; } /** @@ -326,14 +285,10 @@ bool Encoder::GetStopped() const { */ bool Encoder::GetDirection() const { if (StatusIsFatal()) return false; - if (m_counter) { - return m_counter->GetDirection(); - } else { - int32_t status = 0; - bool value = getEncoderDirection(m_encoder, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - return value; - } + int32_t status = 0; + bool value = getEncoderDirection(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return value; } /** @@ -342,16 +297,10 @@ bool Encoder::GetDirection() const { */ double Encoder::DecodingScaleFactor() const { if (StatusIsFatal()) return 0.0; - switch (m_encodingType) { - case k1X: - return 1.0; - case k2X: - return 0.5; - case k4X: - return 0.25; - default: - return 0.0; - } + int32_t status = 0; + double val = getEncoderDecodingScaleFactor(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return val; } /** @@ -362,7 +311,10 @@ double Encoder::DecodingScaleFactor() const { */ double Encoder::GetDistance() const { if (StatusIsFatal()) return 0.0; - return GetRaw() * DecodingScaleFactor() * m_distancePerPulse; + int32_t status = 0; + double value = getEncoderDistance(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return value; } /** @@ -375,7 +327,10 @@ double Encoder::GetDistance() const { */ double Encoder::GetRate() const { if (StatusIsFatal()) return 0.0; - return (m_distancePerPulse / GetPeriod()); + int32_t status = 0; + double value = getEncoderRate(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return value; } /** @@ -386,7 +341,9 @@ double Encoder::GetRate() const { */ void Encoder::SetMinRate(double minRate) { if (StatusIsFatal()) return; - SetMaxPeriod(m_distancePerPulse / minRate); + int32_t status = 0; + setEncoderMinRate(m_encoder, minRate, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); } /** @@ -408,7 +365,9 @@ void Encoder::SetMinRate(double minRate) { */ void Encoder::SetDistancePerPulse(double distancePerPulse) { if (StatusIsFatal()) return; - m_distancePerPulse = distancePerPulse; + int32_t status = 0; + setEncoderDistancePerPulse(m_encoder, distancePerPulse, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); } /** @@ -421,13 +380,9 @@ void Encoder::SetDistancePerPulse(double distancePerPulse) { */ void Encoder::SetReverseDirection(bool reverseDirection) { if (StatusIsFatal()) return; - if (m_counter) { - m_counter->SetReverseDirection(reverseDirection); - } else { - int32_t status = 0; - setEncoderReverseDirection(m_encoder, reverseDirection, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - } + int32_t status = 0; + setEncoderReverseDirection(m_encoder, reverseDirection, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); } /** @@ -444,18 +399,11 @@ void Encoder::SetSamplesToAverage(int samplesToAverage) { wpi_setWPIErrorWithContext( ParameterOutOfRange, "Average counter values must be between 1 and 127"); + return; } int32_t status = 0; - switch (m_encodingType) { - case k4X: - setEncoderSamplesToAverage(m_encoder, samplesToAverage, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - break; - case k1X: - case k2X: - m_counter->SetSamplesToAverage(samplesToAverage); - break; - } + setEncoderSamplesToAverage(m_encoder, samplesToAverage, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); } /** @@ -468,18 +416,9 @@ void Encoder::SetSamplesToAverage(int samplesToAverage) { * @return The number of samples being averaged (from 1 to 127) */ int Encoder::GetSamplesToAverage() const { - int result = 1; int32_t status = 0; - switch (m_encodingType) { - case k4X: - result = getEncoderSamplesToAverage(m_encoder, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - break; - case k1X: - case k2X: - result = m_counter->GetSamplesToAverage(); - break; - } + int result = getEncoderSamplesToAverage(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); return result; } @@ -510,13 +449,9 @@ double Encoder::PIDGet() { */ void Encoder::SetIndexSource(uint32_t channel, Encoder::IndexingType type) { int32_t status = 0; - bool activeHigh = (type == kResetWhileHigh) || (type == kResetOnRisingEdge); - bool edgeSensitive = - (type == kResetOnFallingEdge) || (type == kResetOnRisingEdge); - - setEncoderIndexSource(m_encoder, channel, false, activeHigh, edgeSensitive, + setEncoderIndexSource(m_encoder, channel, false, (EncoderIndexingType)type, &status); - wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status)); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); } /** @@ -544,21 +479,27 @@ void Encoder::SetIndexSource(DigitalSource* source, void Encoder::SetIndexSource(const DigitalSource& source, Encoder::IndexingType type) { int32_t status = 0; - bool activeHigh = (type == kResetWhileHigh) || (type == kResetOnRisingEdge); - bool edgeSensitive = - (type == kResetOnFallingEdge) || (type == kResetOnRisingEdge); - setEncoderIndexSource(m_encoder, source.GetChannelForRouting(), - source.GetAnalogTriggerForRouting(), activeHigh, - edgeSensitive, &status); - wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status)); + source.GetAnalogTriggerForRouting(), + (EncoderIndexingType)type, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); +} + +int32_t Encoder::GetFPGAIndex() const { + int32_t status = 0; + int32_t val = getEncoderFPGAIndex(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return val; } void Encoder::UpdateTable() { if (m_table != nullptr) { m_table->PutNumber("Speed", GetRate()); m_table->PutNumber("Distance", GetDistance()); - m_table->PutNumber("Distance per Tick", m_distancePerPulse); + int32_t status = 0; + double distancePerPulse = getEncoderDistancePerPulse(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_table->PutNumber("Distance per Tick", distancePerPulse); } } @@ -567,7 +508,10 @@ void Encoder::StartLiveWindowMode() {} void Encoder::StopLiveWindowMode() {} std::string Encoder::GetSmartDashboardType() const { - if (m_encodingType == k4X) + int32_t status = 0; + EncoderEncodingType type = getEncoderEncodingType(m_encoder, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + if (type == EncoderEncodingType::HAL_Encoder_k4X) return "Quadrature Encoder"; else return "Encoder"; diff --git a/wpilibj/src/athena/cpp/lib/CounterJNI.cpp b/wpilibj/src/athena/cpp/lib/CounterJNI.cpp index e7d681d8ff..1293b81614 100644 --- a/wpilibj/src/athena/cpp/lib/CounterJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/CounterJNI.cpp @@ -37,9 +37,9 @@ Java_edu_wpi_first_wpilibj_hal_CounterJNI_initializeCounter( COUNTERJNI_LOG(logDEBUG) << "Calling COUNTERJNI initializeCounter"; COUNTERJNI_LOG(logDEBUG) << "Mode = " << mode; jint* indexPtr = (jint*)env->GetDirectBufferAddress(index); - COUNTERJNI_LOG(logDEBUG) << "Index Ptr = " << (uint32_t*)indexPtr; + COUNTERJNI_LOG(logDEBUG) << "Index Ptr = " << (int32_t*)indexPtr; int32_t status = 0; - auto counter = initializeCounter((Mode)mode, (uint32_t*)indexPtr, &status); + auto counter = initializeCounter((Mode)mode, (int32_t*)indexPtr, &status); COUNTERJNI_LOG(logDEBUG) << "Index = " << *indexPtr; COUNTERJNI_LOG(logDEBUG) << "Status = " << status; COUNTERJNI_LOG(logDEBUG) << "COUNTER Handle = " << counter; diff --git a/wpilibj/src/athena/cpp/lib/EncoderJNI.cpp b/wpilibj/src/athena/cpp/lib/EncoderJNI.cpp index d222ed50d0..20b3cedff1 100644 --- a/wpilibj/src/athena/cpp/lib/EncoderJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/EncoderJNI.cpp @@ -29,13 +29,13 @@ extern "C" { /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: initializeEncoder - * Signature: (BIZBIZZLjava/nio/IntBuffer;)J + * Signature: (BIZBIZZI)I */ -JNIEXPORT jlong JNICALL +JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_initializeEncoder( JNIEnv* env, jclass, jbyte port_a_module, jint port_a_pin, jboolean port_a_analog_trigger, jbyte port_b_module, jint port_b_pin, - jboolean port_b_analog_trigger, jboolean reverseDirection, jobject index) { + jboolean port_b_analog_trigger, jboolean reverseDirection, jint encodingType) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI initializeEncoder"; ENCODERJNI_LOG(logDEBUG) << "Module A = " << (jint)port_a_module; ENCODERJNI_LOG(logDEBUG) << "Pin A = " << port_a_pin; @@ -46,46 +46,30 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_initializeEncoder( ENCODERJNI_LOG(logDEBUG) << "Analog Trigger B = " << (jint)port_b_analog_trigger; ENCODERJNI_LOG(logDEBUG) << "Reverse direction = " << (jint)reverseDirection; - jint* indexPtr = (jint*)env->GetDirectBufferAddress(index); - ENCODERJNI_LOG(logDEBUG) << "Index Ptr = " << indexPtr; + ENCODERJNI_LOG(logDEBUG) << "EncodingType = " << encodingType; int32_t status = 0; - void* encoder = initializeEncoder( + auto encoder = initializeEncoder( port_a_module, port_a_pin, port_a_analog_trigger, port_b_module, - port_b_pin, port_b_analog_trigger, reverseDirection, indexPtr, &status); - - ENCODERJNI_LOG(logDEBUG) << "Index = " << *indexPtr; + port_b_pin, port_b_analog_trigger, reverseDirection, + (EncoderEncodingType)encodingType, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; - ENCODERJNI_LOG(logDEBUG) << "ENCODER Ptr = " << encoder; + ENCODERJNI_LOG(logDEBUG) << "ENCODER Handle = " << encoder; CheckStatus(env, status); - return (jlong)encoder; + return (jint)encoder; } /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: freeEncoder - * Signature: (J)V + * Signature: (I)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_freeEncoder( - JNIEnv* env, jclass, jlong id) { + JNIEnv* env, jclass, jint id) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI freeEncoder"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; int32_t status = 0; - freeEncoder((void*)id, &status); - ENCODERJNI_LOG(logDEBUG) << "Status = " << status; - CheckStatus(env, status); -} - -/* - * Class: edu_wpi_first_wpilibj_hal_EncoderJNI - * Method: resetEncoder - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_resetEncoder( - JNIEnv* env, jclass, jlong id) { - ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI resetEncoder"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; - int32_t status = 0; - resetEncoder((void*)id, &status); + freeEncoder((HalEncoderHandle)id, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -93,34 +77,83 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_resetEncoder( /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: getEncoder - * Signature: (J)I + * Signature: (I)I */ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoder( - JNIEnv* env, jclass, jlong id) { + JNIEnv* env, jclass, jint id) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoder"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; int32_t status = 0; - jint returnValue = getEncoder((void*)id, &status); + jint returnValue = getEncoder((HalEncoderHandle)id, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; ENCODERJNI_LOG(logDEBUG) << "getEncoderResult = " << returnValue; CheckStatus(env, status); return returnValue; } +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: getEncoderRaw + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderRaw( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderRaw"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + jint returnValue = getEncoderRaw((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + ENCODERJNI_LOG(logDEBUG) << "getRawEncoderResult = " << returnValue; + CheckStatus(env, status); + return returnValue; +} + +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: getEncodingScaleFactor + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncodingScaleFactor( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncodingScaleFactor"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + jint returnValue = getEncoderEncodingScale((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + ENCODERJNI_LOG(logDEBUG) << "getEncodingScaleFactorResult = " << returnValue; + CheckStatus(env, status); + return returnValue; +} + +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: resetEncoder + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_resetEncoder( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI resetEncoder"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + resetEncoder((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + CheckStatus(env, status); +} + /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: getEncoderPeriod - * Signature: (J)D + * Signature: (I)D */ JNIEXPORT jdouble JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderPeriod( - JNIEnv* env, jclass, jlong id) { + JNIEnv* env, jclass, jint id) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderPeriod"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; int32_t status = 0; - double returnValue = getEncoderPeriod((void*)id, &status); + double returnValue = getEncoderPeriod((HalEncoderHandle)id, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; - ENCODERJNI_LOG(logDEBUG) << "getEncoderPeriodResult = " << returnValue; + ENCODERJNI_LOG(logDEBUG) << "getEncoderPeriodEncoderResult = " << returnValue; CheckStatus(env, status); return returnValue; } @@ -128,15 +161,15 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderPeriod( /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: setEncoderMaxPeriod - * Signature: (JD)V + * Signature: (ID)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderMaxPeriod( - JNIEnv* env, jclass, jlong id, jdouble value) { + JNIEnv* env, jclass, jint id, jdouble value) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderMaxPeriod"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; int32_t status = 0; - setEncoderMaxPeriod((void*)id, value, &status); + setEncoderMaxPeriod((HalEncoderHandle)id, value, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -144,17 +177,17 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderMaxPeriod( /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: getEncoderStopped - * Signature: (J)Z + * Signature: (I)Z */ JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderStopped( - JNIEnv* env, jclass, jlong id) { + JNIEnv* env, jclass, jint id) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderStopped"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; int32_t status = 0; - jboolean returnValue = getEncoderStopped((void*)id, &status); + jboolean returnValue = getEncoderStopped((HalEncoderHandle)id, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; - ENCODERJNI_LOG(logDEBUG) << "getEncoderStoppedResult = " << returnValue; + ENCODERJNI_LOG(logDEBUG) << "getStoppedEncoderResult = " << returnValue; CheckStatus(env, status); return returnValue; } @@ -162,33 +195,101 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderStopped( /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: getEncoderDirection - * Signature: (J)Z + * Signature: (I)Z */ JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderDirection( - JNIEnv* env, jclass, jlong id) { + JNIEnv* env, jclass, jint id) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderDirection"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; int32_t status = 0; - jboolean returnValue = getEncoderDirection((void*)id, &status); + jboolean returnValue = getEncoderDirection((HalEncoderHandle)id, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; - ENCODERJNI_LOG(logDEBUG) << "getEncoderDirectionResult = " << returnValue; + ENCODERJNI_LOG(logDEBUG) << "getDirectionEncoderResult = " << returnValue; CheckStatus(env, status); return returnValue; } +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: getEncoderDistance + * Signature: (I)D + */ +JNIEXPORT jdouble JNICALL +Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderDistance( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderDistance"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + jdouble returnValue = getEncoderDistance((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + ENCODERJNI_LOG(logDEBUG) << "getDistanceEncoderResult = " << returnValue; + CheckStatus(env, status); + return returnValue; +} + +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: getEncoderRate + * Signature: (I)D + */ +JNIEXPORT jdouble JNICALL +Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderRate( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderRate"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + jdouble returnValue = getEncoderRate((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + ENCODERJNI_LOG(logDEBUG) << "getRateEncoderResult = " << returnValue; + CheckStatus(env, status); + return returnValue; +} + +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: setEncoderMinRate + * Signature: (ID)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderMinRate( + JNIEnv* env, jclass, jint id, jdouble value) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderMinRate"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + setEncoderMinRate((HalEncoderHandle)id, value, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + CheckStatus(env, status); +} + +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: setEncoderDistancePerPulse + * Signature: (ID)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderDistancePerPulse( + JNIEnv* env, jclass, jint id, jdouble value) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderDistancePerPulse"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + setEncoderDistancePerPulse((HalEncoderHandle)id, value, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + CheckStatus(env, status); +} + /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: setEncoderReverseDirection - * Signature: (JZ)V + * Signature: (IZ)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderReverseDirection( - JNIEnv* env, jclass, jlong id, jboolean value) { + JNIEnv* env, jclass, jint id, jboolean value) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderReverseDirection"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; int32_t status = 0; - setEncoderReverseDirection((void*)id, value, &status); + setEncoderReverseDirection((HalEncoderHandle)id, value, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -196,15 +297,15 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderReverseDirection( /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: setEncoderSamplesToAverage - * Signature: (JI)V + * Signature: (II)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderSamplesToAverage( - JNIEnv* env, jclass, jlong id, jint value) { + JNIEnv* env, jclass, jint id, jint value) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderSamplesToAverage"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; int32_t status = 0; - setEncoderSamplesToAverage((void*)id, value, &status); + setEncoderSamplesToAverage((HalEncoderHandle)id, value, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; if (status == PARAMETER_OUT_OF_RANGE) { ThrowBoundaryException(env, value, 1, 127); @@ -216,15 +317,15 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderSamplesToAverage( /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: getEncoderSamplesToAverage - * Signature: (J)I + * Signature: (I)I */ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderSamplesToAverage( - JNIEnv* env, jclass, jlong id) { + JNIEnv* env, jclass, jint id) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; int32_t status = 0; - jint returnValue = getEncoderSamplesToAverage((void*)id, &status); + jint returnValue = getEncoderSamplesToAverage((HalEncoderHandle)id, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = " << returnValue; @@ -235,26 +336,118 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderSamplesToAverage( /* * Class: edu_wpi_first_wpilibj_hal_EncoderJNI * Method: setEncoderIndexSource - * Signature: (JIZZZ)V + * Signature: (IIZI)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderIndexSource( - JNIEnv* env, jclass, jlong id, jint pin, jboolean analogTrigger, - jboolean activeHigh, jboolean edgeSensitive) { + JNIEnv* env, jclass, jint id, jint pin, jboolean analogTrigger, + jint type) { ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderIndexSource"; - ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; ENCODERJNI_LOG(logDEBUG) << "Pin = " << pin; ENCODERJNI_LOG(logDEBUG) << "Analog Trigger = " << (analogTrigger ? "true" : "false"); - ENCODERJNI_LOG(logDEBUG) << "Active High = " - << (activeHigh ? "true" : "false"); - ENCODERJNI_LOG(logDEBUG) << "Edge Sensitive = " - << (edgeSensitive ? "true" : "false"); + ENCODERJNI_LOG(logDEBUG) << "IndexingType = " << type; int32_t status = 0; - setEncoderIndexSource((void*)id, pin, analogTrigger, activeHigh, - edgeSensitive, &status); + setEncoderIndexSource((HalEncoderHandle)id, pin, analogTrigger, + (EncoderIndexingType)type, &status); ENCODERJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: getEncoderFPGAIndex + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderFPGAIndex( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + jint returnValue = getEncoderFPGAIndex((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = " + << returnValue; + CheckStatus(env, status); + return returnValue; +} + +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: getEncoderEncodingScale + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderEncodingScale( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + jint returnValue = getEncoderEncodingScale((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = " + << returnValue; + CheckStatus(env, status); + return returnValue; +} + +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: getEncoderDecodingScaleFactor + * Signature: (I)D + */ +JNIEXPORT jdouble JNICALL +Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderDecodingScaleFactor( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + jint returnValue = getEncoderDecodingScaleFactor((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = " + << returnValue; + CheckStatus(env, status); + return returnValue; +} + +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: getEncoderDistancePerPulse + * Signature: (I)D + */ +JNIEXPORT jdouble JNICALL +Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderDistancePerPulse( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + jint returnValue = getEncoderDistancePerPulse((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = " + << returnValue; + CheckStatus(env, status); + return returnValue; +} + +/* + * Class: edu_wpi_first_wpilibj_hal_EncoderJNI + * Method: getEncoderEncodingType + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderEncodingType( + JNIEnv* env, jclass, jint id) { + ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage"; + ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id; + int32_t status = 0; + jint returnValue = getEncoderEncodingType((HalEncoderHandle)id, &status); + ENCODERJNI_LOG(logDEBUG) << "Status = " << status; + ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = " + << returnValue; + CheckStatus(env, status); + return returnValue; +} + } // extern "C" diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Encoder.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Encoder.java index c50af11376..d25e4368d6 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Encoder.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Encoder.java @@ -31,7 +31,14 @@ import edu.wpi.first.wpilibj.tables.ITable; */ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveWindowSendable { public enum IndexingType { - kResetWhileHigh, kResetWhileLow, kResetOnFallingEdge, kResetOnRisingEdge + kResetWhileHigh(0), kResetWhileLow(1), kResetOnFallingEdge(2), kResetOnRisingEdge(3); + + @SuppressWarnings("MemberName") + public final int value; + + IndexingType(int value) { + this.value = value; + } } /** @@ -48,24 +55,13 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * The index source. */ protected DigitalSource m_indexSource = null; // Index on some encoders - private long m_encoder; - private int m_index; - private double m_distancePerPulse; // distance of travel for each encoder - // tick - private Counter m_counter; // Counter object for 1x and 2x encoding - /** - * Either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is selected, then an encoder - * FPGA object is used and the returned counts will be 4x the encoder spec'd value since all - * rising and falling edges are counted. If 1X or 2X are selected then a counter object will be - * used and the returned value will either exactly match the spec'd count or be double (2x) the - * spec'd count. - */ - private EncodingType m_encodingType = EncodingType.k4X; - private int m_encodingScale; // 1x, 2x, or 4x, per the m_encodingType private boolean m_allocatedA; private boolean m_allocatedB; private boolean m_allocatedI; private PIDSourceType m_pidSource; + + private int m_encoder; // the HAL encoder object + /** * Common initialization code for Encoders. This code allocates resources for Encoders and is @@ -75,36 +71,15 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * * @param reverseDirection If true, counts down instead of up (this is all relative) */ - private void initEncoder(boolean reverseDirection) { - switch (m_encodingType) { - case k4X: - m_encodingScale = 4; - ByteBuffer index = ByteBuffer.allocateDirect(4); - // set the byte order - index.order(ByteOrder.LITTLE_ENDIAN); - m_encoder = - EncoderJNI.initializeEncoder(m_aSource.getModuleForRouting(), m_aSource - .getChannelForRouting(), m_aSource.getAnalogTriggerForRouting(), - m_bSource.getModuleForRouting(), m_bSource.getChannelForRouting(), - m_bSource.getAnalogTriggerForRouting(), - reverseDirection, index.asIntBuffer()); - m_index = index.asIntBuffer().get(0); - m_counter = null; - setMaxPeriod(.5); - break; - case k2X: - case k1X: - m_encodingScale = m_encodingType == EncodingType.k1X ? 1 : 2; - m_counter = new Counter(m_encodingType, m_aSource, m_bSource, reverseDirection); - m_index = m_counter.getFPGAIndex(); - break; - default: - throw new AssertionError("Illegal encoding type: " + m_encodingType); - } - m_distancePerPulse = 1.0; + private void initEncoder(boolean reverseDirection, final EncodingType type) { + m_encoder = EncoderJNI.initializeEncoder(m_aSource.getModuleForRouting(), + (byte)m_aSource.getChannelForRouting(), m_aSource.getAnalogTriggerForRouting(), + m_bSource.getModuleForRouting(), (byte)m_bSource.getChannelForRouting(), + m_bSource.getAnalogTriggerForRouting(), reverseDirection, type.value); + m_pidSource = PIDSourceType.kDisplacement; - UsageReporting.report(tResourceType.kResourceType_Encoder, m_index, m_encodingType.value); + UsageReporting.report(tResourceType.kResourceType_Encoder, getFPGAIndex(), type.value); LiveWindow.addSensor("Encoder", m_aSource.getChannelForRouting(), this); } @@ -124,7 +99,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW m_allocatedI = false; m_aSource = new DigitalInput(channelA); m_bSource = new DigitalInput(channelB); - initEncoder(reverseDirection); + initEncoder(reverseDirection, EncodingType.k4X); } /** @@ -163,10 +138,9 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW if (encodingType == null) { throw new NullPointerException("Given encoding type was null"); } - m_encodingType = encodingType; m_aSource = new DigitalInput(channelA); m_bSource = new DigitalInput(channelB); - initEncoder(reverseDirection); + initEncoder(reverseDirection, encodingType); } /** @@ -189,7 +163,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW m_aSource = new DigitalInput(channelA); m_bSource = new DigitalInput(channelB); m_indexSource = new DigitalInput(indexChannel); - initEncoder(reverseDirection); + initEncoder(reverseDirection, EncodingType.k4X); setIndexSource(indexChannel); } @@ -231,7 +205,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW throw new NullPointerException("Digital Source B was null"); } m_bSource = sourceB; - initEncoder(reverseDirection); + initEncoder(reverseDirection, EncodingType.k4X); } /** @@ -274,7 +248,6 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW if (encodingType == null) { throw new NullPointerException("Given encoding type was null"); } - m_encodingType = encodingType; if (sourceA == null) { throw new NullPointerException("Digital Source A was null"); } @@ -284,7 +257,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW } m_aSource = sourceA; m_bSource = sourceB; - initEncoder(reverseDirection); + initEncoder(reverseDirection, encodingType); } /** @@ -315,7 +288,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW m_aSource = sourceA; m_bSource = sourceB; m_indexSource = indexSource; - initEncoder(reverseDirection); + initEncoder(reverseDirection, EncodingType.k4X); setIndexSource(indexSource); } @@ -339,7 +312,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW */ @SuppressWarnings("AbbreviationAsWordInName") public int getFPGAIndex() { - return m_index; + return EncoderJNI.getEncoderFPGAIndex(m_encoder); } /** @@ -348,7 +321,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @return The encoding scale factor 1x, 2x, or 4x, per the requested encoding type. */ public int getEncodingScale() { - return m_encodingScale; + return EncoderJNI.getEncoderEncodingScale(m_encoder); } /** @@ -371,12 +344,8 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW m_aSource = null; m_bSource = null; m_indexSource = null; - if (m_counter != null) { - m_counter.free(); - m_counter = null; - } else { - EncoderJNI.freeEncoder(m_encoder); - } + EncoderJNI.freeEncoder(m_encoder); + m_encoder = 0; } /** @@ -386,13 +355,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @return Current raw count from the encoder */ public int getRaw() { - int value; - if (m_counter != null) { - value = m_counter.get(); - } else { - value = EncoderJNI.getEncoder(m_encoder); - } - return value; + return EncoderJNI.getEncoderRaw(m_encoder); } /** @@ -402,18 +365,14 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @return Current count from the Encoder adjusted for the 1x, 2x, or 4x scale factor. */ public int get() { - return (int) (getRaw() * decodingScaleFactor()); + return EncoderJNI.getEncoder(m_encoder); } /** * Reset the Encoder distance to zero. Resets the current count to zero on the encoder. */ public void reset() { - if (m_counter != null) { - m_counter.reset(); - } else { - EncoderJNI.resetEncoder(m_encoder); - } + EncoderJNI.resetEncoder(m_encoder); } /** @@ -428,13 +387,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW */ @Deprecated public double getPeriod() { - double measuredPeriod; - if (m_counter != null) { - measuredPeriod = m_counter.getPeriod() / decodingScaleFactor(); - } else { - measuredPeriod = EncoderJNI.getEncoderPeriod(m_encoder); - } - return measuredPeriod; + return EncoderJNI.getEncoderPeriod(m_encoder); } /** @@ -447,11 +400,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * the device stopped. This is expressed in seconds. */ public void setMaxPeriod(double maxPeriod) { - if (m_counter != null) { - m_counter.setMaxPeriod(maxPeriod * decodingScaleFactor()); - } else { - EncoderJNI.setEncoderMaxPeriod(m_encoder, maxPeriod); - } + EncoderJNI.setEncoderMaxPeriod(m_encoder, maxPeriod); } /** @@ -462,11 +411,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @return True if the encoder is considered stopped. */ public boolean getStopped() { - if (m_counter != null) { - return m_counter.getStopped(); - } else { - return EncoderJNI.getEncoderStopped(m_encoder); - } + return EncoderJNI.getEncoderStopped(m_encoder); } /** @@ -475,28 +420,14 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @return The last direction the encoder value changed. */ public boolean getDirection() { - if (m_counter != null) { - return m_counter.getDirection(); - } else { - return EncoderJNI.getEncoderDirection(m_encoder); - } + return EncoderJNI.getEncoderDirection(m_encoder); } /** * The scale needed to convert a raw counter value into a number of encoder pulses. */ private double decodingScaleFactor() { - switch (m_encodingType) { - case k1X: - return 1.0; - case k2X: - return 0.5; - case k4X: - return 0.25; - default: - // This is never reached, EncodingType enum limits values - return 0.0; - } + return EncoderJNI.getEncoderDecodingScaleFactor(m_encoder); } /** @@ -506,7 +437,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @return The distance driven since the last reset */ public double getDistance() { - return getRaw() * decodingScaleFactor() * m_distancePerPulse; + return EncoderJNI.getEncoderDistance(m_encoder); } /** @@ -516,7 +447,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @return The current rate of the encoder. */ public double getRate() { - return m_distancePerPulse / getPeriod(); + return EncoderJNI.getEncoderRate(m_encoder); } /** @@ -526,7 +457,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * from setDistancePerPulse(). */ public void setMinRate(double minRate) { - setMaxPeriod(m_distancePerPulse / minRate); + EncoderJNI.setEncoderMinRate(m_encoder, minRate); } /** @@ -539,7 +470,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @param distancePerPulse The scale factor that will be used to convert pulses to useful units. */ public void setDistancePerPulse(double distancePerPulse) { - m_distancePerPulse = distancePerPulse; + EncoderJNI.setEncoderDistancePerPulse(m_encoder, distancePerPulse); } /** @@ -549,9 +480,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @param reverseDirection true if the encoder direction should be reversed */ public void setReverseDirection(boolean reverseDirection) { - if (m_counter != null) { - m_counter.setReverseDirection(reverseDirection); - } + EncoderJNI.setEncoderReverseDirection(m_encoder, reverseDirection); } /** @@ -562,17 +491,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @param samplesToAverage The number of samples to average from 1 to 127. */ public void setSamplesToAverage(int samplesToAverage) { - switch (m_encodingType) { - case k4X: - EncoderJNI.setEncoderSamplesToAverage(m_encoder, samplesToAverage); - break; - case k1X: - case k2X: - m_counter.setSamplesToAverage(samplesToAverage); - break; - default: - throw new AssertionError("Illegal encoding type: " + m_encodingType); - } + EncoderJNI.setEncoderSamplesToAverage(m_encoder, samplesToAverage); } /** @@ -583,15 +502,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @return SamplesToAverage The number of samples being averaged (from 1 to 127) */ public int getSamplesToAverage() { - switch (m_encodingType) { - case k4X: - return EncoderJNI.getEncoderSamplesToAverage(m_encoder); - case k1X: - case k2X: - return m_counter.getSamplesToAverage(); - default: - return 1; - } + return EncoderJNI.getEncoderSamplesToAverage(m_encoder); } /** @@ -653,12 +564,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @param type The state that will cause the encoder to reset */ public void setIndexSource(int channel, IndexingType type) { - boolean activeHigh = - (type == IndexingType.kResetWhileHigh) || (type == IndexingType.kResetOnRisingEdge); - boolean edgeSensitive = - (type == IndexingType.kResetOnFallingEdge) || (type == IndexingType.kResetOnRisingEdge); - - EncoderJNI.setEncoderIndexSource(m_encoder, channel, false, activeHigh, edgeSensitive); + EncoderJNI.setEncoderIndexSource(m_encoder, channel, false, type.value); } /** @@ -669,21 +575,16 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW * @param type The state that will cause the encoder to reset */ public void setIndexSource(DigitalSource source, IndexingType type) { - boolean activeHigh = - (type == IndexingType.kResetWhileHigh) || (type == IndexingType.kResetOnRisingEdge); - boolean edgeSensitive = - (type == IndexingType.kResetOnFallingEdge) || (type == IndexingType.kResetOnRisingEdge); - - EncoderJNI.setEncoderIndexSource(m_encoder, source.getChannelForRouting(), - source.getAnalogTriggerForRouting(), activeHigh, edgeSensitive); + EncoderJNI.setEncoderIndexSource(m_encoder, source.getChannelForRouting(), + source.getAnalogTriggerForRouting(), type.value); } /** * Live Window code, only does anything if live window is activated. */ public String getSmartDashboardType() { - switch (m_encodingType) { - case k4X: + switch (EncoderJNI.getEncoderEncodingType(m_encoder)) { + case 2: // value of k4X return "Quadrature Encoder"; default: return "Encoder"; @@ -708,7 +609,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW if (m_table != null) { m_table.putNumber("Speed", getRate()); m_table.putNumber("Distance", getDistance()); - m_table.putNumber("Distance per Tick", m_distancePerPulse); + m_table.putNumber("Distance per Tick", EncoderJNI.getEncoderDistancePerPulse(m_encoder)); } } diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java index 7c92636bd4..f30ed7bd44 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java @@ -10,34 +10,57 @@ package edu.wpi.first.wpilibj.hal; import java.nio.IntBuffer; public class EncoderJNI extends JNIWrapper { - public static native long initializeEncoder(byte portAModule, int portAPin, + + public static native int initializeEncoder(byte portAModule, int portAPin, boolean portAAnalogTrigger, byte portBModule, int portBPin, boolean portBAnalogTrigger, - boolean reverseDirection, IntBuffer index); + boolean reverseDirection, int encodingType); - public static native void freeEncoder(long encoderPointer); + public static native void freeEncoder(int encoderHandle); - public static native void resetEncoder(long encoderPointer); + public static native int getEncoder(int encoderHandle); + + public static native int getEncoderRaw(int encoderHandle); + + public static native int getEncodingScaleFactor(int encoderHandle); + + public static native void resetEncoder(int encoderHandle); - public static native int getEncoder(long encoderPointer); + public static native double getEncoderPeriod(int encoderHandle); - public static native double getEncoderPeriod(long encoderPointer); + public static native void setEncoderMaxPeriod(int encoderHandle, double maxPeriod); - public static native void setEncoderMaxPeriod(long encoderPointer, double maxPeriod); + public static native boolean getEncoderStopped(int encoderHandle); - public static native boolean getEncoderStopped(long encoderPointer); + public static native boolean getEncoderDirection(int encoderHandle); + + public static native double getEncoderDistance(int encoderHandle); + + public static native double getEncoderRate(int encoderHandle); + + public static native void setEncoderMinRate(int encoderHandle, double minRate); + + public static native void setEncoderDistancePerPulse(int encoderHandle, double distancePerPulse); - public static native boolean getEncoderDirection(long encoderPointer); - - public static native void setEncoderReverseDirection(long encoderPointer, + public static native void setEncoderReverseDirection(int encoderHandle, boolean reverseDirection); - public static native void setEncoderSamplesToAverage(long encoderPointer, + public static native void setEncoderSamplesToAverage(int encoderHandle, int samplesToAverage); - public static native int getEncoderSamplesToAverage(long encoderPointer); + public static native int getEncoderSamplesToAverage(int encoderHandle); - public static native void setEncoderIndexSource(long digitalPort, int pin, - boolean analogTrigger, boolean activeHigh, - boolean edgeSensitive); + public static native void setEncoderIndexSource(int encoderHandle, int pin, + boolean analogTrigger, int indexingType); + + @SuppressWarnings("AbbreviationAsWordInName") + public static native int getEncoderFPGAIndex(int encoderHandle); + + public static native int getEncoderEncodingScale(int encoderHandle); + + public static native double getEncoderDecodingScaleFactor(int encoderHandle); + + public static native double getEncoderDistancePerPulse(int encoderHandle); + + public static native int getEncoderEncodingType(int encoderHandle); }