Skip to content

Commit

Permalink
[hal, wpilib] Fix up DIO pulse API (wpilibsuite#4387)
Browse files Browse the repository at this point in the history
The FPGA API takes microseconds directly, instead of a scaled value. Also add a new HAL level API to trigger multiple DIOs with the same pulse at once.
  • Loading branch information
ThadHouse authored Sep 2, 2022
1 parent 59e6706 commit a5df391
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 19 deletions.
4 changes: 3 additions & 1 deletion hal/src/main/java/edu/wpi/first/hal/DIOJNI.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ public class DIOJNI extends JNIWrapper {

public static native boolean getDIODirection(int dioPortHandle);

public static native void pulse(int dioPortHandle, double pulseLength);
public static native void pulse(int dioPortHandle, double pulseLengthSeconds);

public static native void pulseMultiple(long channelMask, double pulseLengthSeconds);

public static native boolean isPulsing(int dioPortHandle);

Expand Down
39 changes: 35 additions & 4 deletions hal/src/main/native/athena/DIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,13 +408,24 @@ HAL_Bool HAL_GetDIODirection(HAL_DigitalHandle dioPortHandle, int32_t* status) {
}
}

void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLength,
void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLengthSeconds,
int32_t* status) {
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}

uint32_t pulseLengthMicroseconds =
static_cast<uint32_t>(pulseLengthSeconds * 1e6);

if (pulseLengthMicroseconds <= 0 || pulseLengthMicroseconds > 0xFFFF) {
*status = PARAMETER_OUT_OF_RANGE;
hal::SetLastError(status,
"Length must be between 1 and 65535 microseconds");
return;
}

tDIO::tPulse pulse;

if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
Expand All @@ -426,9 +437,29 @@ void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLength,
}

digitalSystem->writePulseLength(
static_cast<uint16_t>(1.0e9 * pulseLength /
(pwmSystem->readLoopTiming(status) * 25)),
status);
static_cast<uint16_t>(pulseLengthMicroseconds), status);
digitalSystem->writePulse(pulse, status);
}

void HAL_PulseMultiple(uint32_t channelMask, double pulseLengthSeconds,
int32_t* status) {
uint32_t pulseLengthMicroseconds =
static_cast<uint32_t>(pulseLengthSeconds * 1e6);

if (pulseLengthMicroseconds <= 0 || pulseLengthMicroseconds > 0xFFFF) {
*status = PARAMETER_OUT_OF_RANGE;
hal::SetLastError(status,
"Length must be between 1 and 65535 microseconds");
return;
}

tDIO::tPulse pulse;
pulse.Headers = channelMask & 0x2FF;
pulse.MXP = (channelMask & 0xFFFF) >> 10;
pulse.SPIPort = (channelMask & 0x1F) >> 26;

digitalSystem->writePulseLength(
static_cast<uint16_t>(pulseLengthMicroseconds), status);
digitalSystem->writePulse(pulse, status);
}

Expand Down
14 changes: 14 additions & 0 deletions hal/src/main/native/cpp/jni/DIOJNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,20 @@ Java_edu_wpi_first_hal_DIOJNI_pulse
CheckStatus(env, status);
}

/*
* Class: edu_wpi_first_hal_DIOJNI
* Method: pulseMultiple
* Signature: (JD)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_DIOJNI_pulseMultiple
(JNIEnv* env, jclass, jlong channelMask, jdouble value)
{
int32_t status = 0;
HAL_PulseMultiple(static_cast<uint32_t>(channelMask), value, &status);
CheckStatus(env, status);
}

/*
* Class: edu_wpi_first_hal_DIOJNI
* Method: isPulsing
Expand Down
17 changes: 15 additions & 2 deletions hal/src/main/native/include/hal/DIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,25 @@ HAL_Bool HAL_GetDIODirection(HAL_DigitalHandle dioPortHandle, int32_t* status);
* single pulse going at any time.
*
* @param[in] dioPortHandle the digital port handle
* @param[in] pulseLength the active length of the pulse (in seconds)
* @param[in] pulseLengthSeconds the active length of the pulse (in seconds)
* @param[out] status Error status variable. 0 on success.
*/
void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLength,
void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLengthSeconds,
int32_t* status);

/**
* Generates a single digital pulse on multiple channels.
*
* Write a pulse to the channels enabled by the mask. There can only be a
* single pulse going at any time.
*
* @param[in] channelMask the channel mask
* @param[in] pulseLengthSeconds the active length of the pulse (in seconds)
* @param[out] status Error status variable. 0 on success.
*/
void HAL_PulseMultiple(uint32_t channelMask, double pulseLengthSeconds,
int32_t* status);

/**
* Checks a DIO line to see if it is currently generating a pulse.
*
Expand Down
7 changes: 6 additions & 1 deletion hal/src/main/native/sim/DIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ HAL_Bool HAL_GetDIODirection(HAL_DigitalHandle dioPortHandle, int32_t* status) {
return value;
}

void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLength,
void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLengthSeconds,
int32_t* status) {
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
Expand All @@ -235,6 +235,11 @@ void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLength,
// TODO (Thad) Add this
}

void HAL_PulseMultiple(uint32_t channelMask, double pulseLengthSeconds,
int32_t* status) {
// TODO (Thad) Add this
}

HAL_Bool HAL_IsPulsing(HAL_DigitalHandle dioPortHandle, int32_t* status) {
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
Expand Down
4 changes: 2 additions & 2 deletions wpilibc/src/main/native/cpp/DigitalOutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ int DigitalOutput::GetChannel() const {
return m_channel;
}

void DigitalOutput::Pulse(double length) {
void DigitalOutput::Pulse(units::second_t pulseLength) {
int32_t status = 0;
HAL_Pulse(m_handle, length, &status);
HAL_Pulse(m_handle, pulseLength.to<double>(), &status);
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
}

Expand Down
7 changes: 4 additions & 3 deletions wpilibc/src/main/native/include/frc/DigitalOutput.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#pragma once

#include <hal/Types.h>
#include <units/time.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>

Expand Down Expand Up @@ -79,11 +80,11 @@ class DigitalOutput : public DigitalSource,
* Output a single pulse on the digital output line.
*
* Send a single pulse on the digital output line where the pulse duration is
* specified in seconds. Maximum pulse length is 0.0016 seconds.
* specified in seconds. Maximum of 65535 microseconds.
*
* @param length The pulse length in seconds
* @param pulseLength The pulse length in seconds
*/
void Pulse(double length);
void Pulse(units::second_t pulseLength);

/**
* Determine if the pulse is still going.
Expand Down
4 changes: 2 additions & 2 deletions wpilibc/src/main/native/include/frc/Ultrasonic.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ class Ultrasonic : public wpi::Sendable,
*/
static void UltrasonicChecker();

// Time (sec) for the ping trigger pulse.
static constexpr double kPingTime = 10 * 1e-6;
// Time (usec) for the ping trigger pulse.
static constexpr auto kPingTime = 10_us;

// Max time (ms) between readings.
static constexpr auto kMaxUltrasonicTime = 0.1_s;
Expand Down
11 changes: 7 additions & 4 deletions wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalOutput.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,15 @@ public int getChannel() {
}

/**
* Generate a single pulse. There can only be a single pulse going at any time.
* Output a single pulse on the digital output line.
*
* @param pulseLength The length of the pulse.
* <p>Send a single pulse on the digital output line where the pulse duration is specified in
* seconds. Maximum of 65535 microseconds.
*
* @param pulseLengthSeconds The pulse length in seconds
*/
public void pulse(final double pulseLength) {
DIOJNI.pulse(m_handle, pulseLength);
public void pulse(final double pulseLengthSeconds) {
DIOJNI.pulse(m_handle, pulseLengthSeconds);
}

/**
Expand Down

0 comments on commit a5df391

Please sign in to comment.