diff --git a/hal/src/main/java/edu/wpi/first/hal/SPIJNI.java b/hal/src/main/java/edu/wpi/first/hal/SPIJNI.java index 05ac08af9b..0652c3fa4a 100644 --- a/hal/src/main/java/edu/wpi/first/hal/SPIJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/SPIJNI.java @@ -8,6 +8,18 @@ import java.nio.ByteBuffer; @SuppressWarnings("AbbreviationAsWordInName") public class SPIJNI extends JNIWrapper { + public static final int INVALID_PORT = -1; + public static final int ONBOARD_CS0_PORT = 0; + public static final int ONBOARD_CS1_PORT = 1; + public static final int ONBOARD_CS2_PORT = 2; + public static final int ONBOARD_CS3_PORT = 3; + public static final int MXP_PORT = 4; + + public static final int SPI_MODE0 = 0; + public static final int SPI_MODE1 = 1; + public static final int SPI_MODE2 = 2; + public static final int SPI_MODE3 = 3; + public static native void spiInitialize(int port); public static native int spiTransaction( @@ -28,8 +40,9 @@ public class SPIJNI extends JNIWrapper { public static native void spiSetSpeed(int port, int speed); - public static native void spiSetOpts( - int port, int msbFirst, int sampleOnTrailing, int clkIdleHigh); + public static native void spiSetMode(int port, int mode); + + public static native int spiGetMode(int port); public static native void spiSetChipSelectActiveHigh(int port); diff --git a/hal/src/main/native/athena/SPI.cpp b/hal/src/main/native/athena/SPI.cpp index 0df6fdb824..e2f5f98e49 100644 --- a/hal/src/main/native/athena/SPI.cpp +++ b/hal/src/main/native/athena/SPI.cpp @@ -364,19 +364,27 @@ void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) { ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MAX_SPEED_HZ, &speed); } -void HAL_SetSPIOpts(HAL_SPIPort port, HAL_Bool msbFirst, - HAL_Bool sampleOnTrailing, HAL_Bool clkIdleHigh) { +void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode) { if (port < 0 || port >= kSpiMaxHandles) { return; } - uint8_t mode = 0; - mode |= (!msbFirst ? 8 : 0); - mode |= (clkIdleHigh ? 2 : 0); - mode |= (sampleOnTrailing ? 1 : 0); + uint8_t mode8 = mode & SPI_MODE_3; std::scoped_lock lock(spiApiMutexes[port]); - ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MODE, &mode); + ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MODE, &mode8); +} + +HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port) { + if (port < 0 || port >= kSpiMaxHandles) { + return HAL_SPI_kMode0; + } + + uint8_t mode8 = 0; + + std::scoped_lock lock(spiApiMutexes[port]); + ioctl(HAL_GetSPIHandle(port), SPI_IOC_RD_MODE, &mode8); + return static_cast(mode8 & SPI_MODE_3); } void HAL_SetSPIChipSelectActiveHigh(HAL_SPIPort port, int32_t* status) { diff --git a/hal/src/main/native/cpp/jni/SPIJNI.cpp b/hal/src/main/native/cpp/jni/SPIJNI.cpp index 3c9143bbb4..4f1e5568ef 100644 --- a/hal/src/main/native/cpp/jni/SPIJNI.cpp +++ b/hal/src/main/native/cpp/jni/SPIJNI.cpp @@ -15,6 +15,27 @@ using namespace hal; using namespace wpi::java; +static_assert(HAL_SPIPort::HAL_SPI_kInvalid == + edu_wpi_first_hal_SPIJNI_INVALID_PORT); +static_assert(HAL_SPIPort::HAL_SPI_kOnboardCS0 == + edu_wpi_first_hal_SPIJNI_ONBOARD_CS0_PORT); +static_assert(HAL_SPIPort::HAL_SPI_kOnboardCS1 == + edu_wpi_first_hal_SPIJNI_ONBOARD_CS1_PORT); +static_assert(HAL_SPIPort::HAL_SPI_kOnboardCS2 == + edu_wpi_first_hal_SPIJNI_ONBOARD_CS2_PORT); +static_assert(HAL_SPIPort::HAL_SPI_kOnboardCS3 == + edu_wpi_first_hal_SPIJNI_ONBOARD_CS3_PORT); +static_assert(HAL_SPIPort::HAL_SPI_kMXP == edu_wpi_first_hal_SPIJNI_MXP_PORT); + +static_assert(HAL_SPIMode::HAL_SPI_kMode0 == + edu_wpi_first_hal_SPIJNI_SPI_MODE0); +static_assert(HAL_SPIMode::HAL_SPI_kMode1 == + edu_wpi_first_hal_SPIJNI_SPI_MODE1); +static_assert(HAL_SPIMode::HAL_SPI_kMode2 == + edu_wpi_first_hal_SPIJNI_SPI_MODE2); +static_assert(HAL_SPIMode::HAL_SPI_kMode3 == + edu_wpi_first_hal_SPIJNI_SPI_MODE3); + extern "C" { /* @@ -202,16 +223,27 @@ Java_edu_wpi_first_hal_SPIJNI_spiSetSpeed /* * Class: edu_wpi_first_hal_SPIJNI - * Method: spiSetOpts - * Signature: (IIII)V + * Method: spiSetMode + * Signature: (II)V */ JNIEXPORT void JNICALL -Java_edu_wpi_first_hal_SPIJNI_spiSetOpts - (JNIEnv*, jclass, jint port, jint msb_first, jint sample_on_trailing, - jint clk_idle_high) +Java_edu_wpi_first_hal_SPIJNI_spiSetMode + (JNIEnv*, jclass, jint port, jint mode) { - HAL_SetSPIOpts(static_cast(port), msb_first, sample_on_trailing, - clk_idle_high); + HAL_SetSPIMode(static_cast(port), + static_cast(mode)); +} + +/* + * Class: edu_wpi_first_hal_SPIJNI + * Method: spiGetMode + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +Java_edu_wpi_first_hal_SPIJNI_spiGetMode + (JNIEnv*, jclass, jint port) +{ + return static_cast(HAL_GetSPIMode(static_cast(port))); } /* diff --git a/hal/src/main/native/include/hal/SPI.h b/hal/src/main/native/include/hal/SPI.h index 84cec5ddb9..f3c7fdca09 100644 --- a/hal/src/main/native/include/hal/SPI.h +++ b/hal/src/main/native/include/hal/SPI.h @@ -90,23 +90,27 @@ void HAL_CloseSPI(HAL_SPIPort port); * * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for * MXP - * @param speed The speed in Hz (0-1MHz) + * @param speed The speed in Hz (500KHz-10MHz) */ void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed); /** - * Sets the SPI options. + * Sets the SPI Mode. * - * @param port The number of the port to use. 0-3 for Onboard - * CS0-CS2, 4 for MXP - * @param msbFirst True to write the MSB first, False for LSB first - * @param sampleOnTrailing True to sample on the trailing edge, False to sample - * on the leading edge - * @param clkIdleHigh True to set the clock to active low, False to set the - * clock active high + * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for + * MXP + * @param mode The SPI mode to use */ -void HAL_SetSPIOpts(HAL_SPIPort port, HAL_Bool msbFirst, - HAL_Bool sampleOnTrailing, HAL_Bool clkIdleHigh); +void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode); + +/** + * Gets the SPI Mode. + * + * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for + * MXP + * @returns The SPI mode currently set + */ +HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port); /** * Sets the CS Active high for a SPI port. diff --git a/hal/src/main/native/include/hal/SPITypes.h b/hal/src/main/native/include/hal/SPITypes.h index de6622682e..34b5d618d6 100644 --- a/hal/src/main/native/include/hal/SPITypes.h +++ b/hal/src/main/native/include/hal/SPITypes.h @@ -25,6 +25,15 @@ HAL_ENUM(HAL_SPIPort) { }; // clang-format on +// clang-format off +HAL_ENUM(HAL_SPIMode) { + HAL_SPI_kMode0 = 0, + HAL_SPI_kMode1 = 1, + HAL_SPI_kMode2 = 2, + HAL_SPI_kMode3 = 3, +}; +// clang-format on + #ifdef __cplusplus namespace hal { diff --git a/hal/src/main/native/sim/SPI.cpp b/hal/src/main/native/sim/SPI.cpp index bf362a80bd..70e2bde1dd 100644 --- a/hal/src/main/native/sim/SPI.cpp +++ b/hal/src/main/native/sim/SPI.cpp @@ -34,8 +34,10 @@ void HAL_CloseSPI(HAL_SPIPort port) { SimSPIData[port].initialized = false; } void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) {} -void HAL_SetSPIOpts(HAL_SPIPort port, HAL_Bool msbFirst, - HAL_Bool sampleOnTrailing, HAL_Bool clkIdleHigh) {} +void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode) {} +HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port) { + return HAL_SPI_kMode0; +} void HAL_SetSPIChipSelectActiveHigh(HAL_SPIPort port, int32_t* status) {} void HAL_SetSPIChipSelectActiveLow(HAL_SPIPort port, int32_t* status) {} int32_t HAL_GetSPIHandle(HAL_SPIPort port) { diff --git a/wpilibc/src/main/native/cpp/ADIS16448_IMU.cpp b/wpilibc/src/main/native/cpp/ADIS16448_IMU.cpp index eb31386746..72d0630549 100644 --- a/wpilibc/src/main/native/cpp/ADIS16448_IMU.cpp +++ b/wpilibc/src/main/native/cpp/ADIS16448_IMU.cpp @@ -197,9 +197,7 @@ bool ADIS16448_IMU::SwitchToStandardSPI() { if (m_spi == nullptr) { m_spi = new SPI(m_spi_port); m_spi->SetClockRate(1000000); - m_spi->SetMSBFirst(); - m_spi->SetSampleDataOnTrailingEdge(); - m_spi->SetClockActiveLow(); + m_spi->SetMode(frc::SPI::Mode::kMode3); m_spi->SetChipSelectActiveLow(); ReadRegister(PROD_ID); // Dummy read diff --git a/wpilibc/src/main/native/cpp/ADIS16470_IMU.cpp b/wpilibc/src/main/native/cpp/ADIS16470_IMU.cpp index 7127fa82ee..f2ff744aa1 100644 --- a/wpilibc/src/main/native/cpp/ADIS16470_IMU.cpp +++ b/wpilibc/src/main/native/cpp/ADIS16470_IMU.cpp @@ -194,9 +194,7 @@ bool ADIS16470_IMU::SwitchToStandardSPI() { if (m_spi == nullptr) { m_spi = new SPI(m_spi_port); m_spi->SetClockRate(2000000); - m_spi->SetMSBFirst(); - m_spi->SetSampleDataOnTrailingEdge(); - m_spi->SetClockActiveLow(); + m_spi->SetMode(frc::SPI::Mode::kMode3); m_spi->SetChipSelectActiveLow(); ReadRegister(PROD_ID); // Dummy read diff --git a/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp b/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp index 9a95bcc163..d3df40017a 100644 --- a/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp +++ b/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp @@ -21,9 +21,7 @@ ADXL345_SPI::ADXL345_SPI(SPI::Port port, ADXL345_SPI::Range range) m_simZ = m_simDevice.CreateDouble("z", hal::SimDevice::kInput, 0.0); } m_spi.SetClockRate(500000); - m_spi.SetMSBFirst(); - m_spi.SetSampleDataOnTrailingEdge(); - m_spi.SetClockActiveLow(); + m_spi.SetMode(frc::SPI::Mode::kMode3); m_spi.SetChipSelectActiveHigh(); uint8_t commands[2]; diff --git a/wpilibc/src/main/native/cpp/ADXL362.cpp b/wpilibc/src/main/native/cpp/ADXL362.cpp index deda965465..be4afb7b9c 100644 --- a/wpilibc/src/main/native/cpp/ADXL362.cpp +++ b/wpilibc/src/main/native/cpp/ADXL362.cpp @@ -43,9 +43,7 @@ ADXL362::ADXL362(SPI::Port port, Range range) } m_spi.SetClockRate(3000000); - m_spi.SetMSBFirst(); - m_spi.SetSampleDataOnTrailingEdge(); - m_spi.SetClockActiveLow(); + m_spi.SetMode(frc::SPI::Mode::kMode3); m_spi.SetChipSelectActiveLow(); uint8_t commands[3]; diff --git a/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp b/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp index 5a2f62543e..542d1ae314 100644 --- a/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp +++ b/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp @@ -38,9 +38,7 @@ ADXRS450_Gyro::ADXRS450_Gyro(SPI::Port port) } m_spi.SetClockRate(3000000); - m_spi.SetMSBFirst(); - m_spi.SetSampleDataOnLeadingEdge(); - m_spi.SetClockActiveHigh(); + m_spi.SetMode(frc::SPI::Mode::kMode0); m_spi.SetChipSelectActiveLow(); if (!m_simDevice) { diff --git a/wpilibc/src/main/native/cpp/SPI.cpp b/wpilibc/src/main/native/cpp/SPI.cpp index bbc82fd729..a629d4de59 100644 --- a/wpilibc/src/main/native/cpp/SPI.cpp +++ b/wpilibc/src/main/native/cpp/SPI.cpp @@ -158,6 +158,7 @@ void SPI::Accumulator::Update() { SPI::SPI(Port port) : m_port(static_cast(port)) { int32_t status = 0; HAL_InitializeSPI(m_port, &status); + HAL_SetSPIMode(m_port, m_mode); FRC_CheckErrorStatus(status, "Port {}", static_cast(m_port)); HAL_Report(HALUsageReporting::kResourceType_SPI, @@ -177,33 +178,46 @@ void SPI::SetClockRate(int hz) { } void SPI::SetMSBFirst() { - m_msbFirst = true; - HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + FRC_ReportError(1, "SetMSBFirst not supported by roboRIO {}", + static_cast(m_port)); } void SPI::SetLSBFirst() { - m_msbFirst = false; - HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + FRC_ReportError(1, "SetLSBFirst not supported by roboRIO {}", + static_cast(m_port)); } void SPI::SetSampleDataOnLeadingEdge() { - m_sampleOnTrailing = false; - HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + int mode = m_mode; + mode &= 2; + m_mode = static_cast(mode); + HAL_SetSPIMode(m_port, m_mode); } void SPI::SetSampleDataOnTrailingEdge() { - m_sampleOnTrailing = true; - HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + int mode = m_mode; + mode |= 2; + m_mode = static_cast(mode); + HAL_SetSPIMode(m_port, m_mode); } void SPI::SetClockActiveLow() { - m_clockIdleHigh = true; - HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + int mode = m_mode; + mode |= 1; + m_mode = static_cast(mode); + HAL_SetSPIMode(m_port, m_mode); } void SPI::SetClockActiveHigh() { - m_clockIdleHigh = false; - HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + int mode = m_mode; + mode &= 1; + m_mode = static_cast(mode); + HAL_SetSPIMode(m_port, m_mode); +} + +void SPI::SetMode(Mode mode) { + m_mode = static_cast(mode & 0x3); + HAL_SetSPIMode(m_port, m_mode); } void SPI::SetChipSelectActiveHigh() { diff --git a/wpilibc/src/main/native/include/frc/SPI.h b/wpilibc/src/main/native/include/frc/SPI.h index fb0e6f50d0..3f51595194 100644 --- a/wpilibc/src/main/native/include/frc/SPI.h +++ b/wpilibc/src/main/native/include/frc/SPI.h @@ -10,6 +10,7 @@ #include #include +#include #include namespace frc { @@ -26,6 +27,12 @@ class DigitalSource; class SPI { public: enum Port { kOnboardCS0 = 0, kOnboardCS1, kOnboardCS2, kOnboardCS3, kMXP }; + enum Mode { + kMode0 = HAL_SPI_kMode0, + kMode1 = HAL_SPI_kMode1, + kMode2 = HAL_SPI_kMode2, + kMode3 = HAL_SPI_kMode3 + }; /** * Constructor @@ -54,39 +61,72 @@ class SPI { /** * Configure the order that bits are sent and received on the wire * to be most significant bit first. + * + * @deprecated Does not work, will be removed. */ + WPI_DEPRECATED("Not supported by roboRIO.") void SetMSBFirst(); /** * Configure the order that bits are sent and received on the wire * to be least significant bit first. + * + * @deprecated Does not work, will be removed. */ + WPI_DEPRECATED("Not supported by roboRIO.") void SetLSBFirst(); /** * Configure that the data is stable on the leading edge and the data * changes on the trailing edge. + * + * @deprecated Use SetMode() instead. */ + WPI_DEPRECATED("Use SetMode() instead") void SetSampleDataOnLeadingEdge(); /** * Configure that the data is stable on the trailing edge and the data * changes on the leading edge. + * + * @deprecated Use SetMode() instead. */ + WPI_DEPRECATED("Use SetMode() instead") void SetSampleDataOnTrailingEdge(); /** * Configure the clock output line to be active low. * This is sometimes called clock polarity high or clock idle high. + * + * @deprecated Use SetMode() instead. */ + WPI_DEPRECATED("Use SetMode() instead") void SetClockActiveLow(); /** * Configure the clock output line to be active high. * This is sometimes called clock polarity low or clock idle low. + * + * @deprecated Use SetMode() instead. */ + WPI_DEPRECATED("Use SetMode() instead") void SetClockActiveHigh(); + /** + * Sets the mode for the SPI device. + * + *

Mode 0 is Clock idle low, data sampled on rising edge + * + *

Mode 1 is Clock idle low, data sampled on falling edge + * + *

Mode 2 is Clock idle high, data sampled on falling edge + * + *

Mode 3 is Clock idle high, data sampled on rising edge + * + * @param mode The mode to set. + */ + void SetMode(Mode mode); + /** * Configure the chip select line to be active high. */ @@ -345,9 +385,7 @@ class SPI { protected: hal::SPIPort m_port; - bool m_msbFirst = false; // Default little-endian - bool m_sampleOnTrailing = false; // Default data updated on falling edge - bool m_clockIdleHigh = false; // Default clock active high + HAL_SPIMode m_mode = HAL_SPIMode::HAL_SPI_kMode0; private: void Init(); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADIS16448_IMU.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADIS16448_IMU.java index cc14a77c97..cbb43e8545 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADIS16448_IMU.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADIS16448_IMU.java @@ -395,9 +395,7 @@ public class ADIS16448_IMU implements AutoCloseable, NTSendable { System.out.println("Setting up a new SPI port."); m_spi = new SPI(m_spi_port); m_spi.setClockRate(1000000); - m_spi.setMSBFirst(); - m_spi.setSampleDataOnTrailingEdge(); - m_spi.setClockActiveLow(); + m_spi.setMode(SPI.Mode.kMode3); m_spi.setChipSelectActiveLow(); readRegister(PROD_ID); // Dummy read diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADIS16470_IMU.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADIS16470_IMU.java index 7741d0118b..b0f90c91bd 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADIS16470_IMU.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADIS16470_IMU.java @@ -438,9 +438,7 @@ public class ADIS16470_IMU implements AutoCloseable, NTSendable { System.out.println("Setting up a new SPI port."); m_spi = new SPI(m_spi_port); m_spi.setClockRate(2000000); - m_spi.setMSBFirst(); - m_spi.setSampleDataOnTrailingEdge(); - m_spi.setClockActiveLow(); + m_spi.setMode(SPI.Mode.kMode3); m_spi.setChipSelectActiveLow(); readRegister(PROD_ID); // Dummy read diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL345_SPI.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL345_SPI.java index fa8b7d808d..ddf38e1c5c 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL345_SPI.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL345_SPI.java @@ -118,9 +118,7 @@ public class ADXL345_SPI implements Accelerometer, NTSendable, AutoCloseable { */ private void init(Range range) { m_spi.setClockRate(500000); - m_spi.setMSBFirst(); - m_spi.setSampleDataOnTrailingEdge(); - m_spi.setClockActiveLow(); + m_spi.setMode(SPI.Mode.kMode3); m_spi.setChipSelectActiveHigh(); // Turn on the measurements diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL362.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL362.java index 2a9c2fe788..19abf05a50 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL362.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL362.java @@ -106,9 +106,7 @@ public class ADXL362 implements Accelerometer, NTSendable, AutoCloseable { } m_spi.setClockRate(3000000); - m_spi.setMSBFirst(); - m_spi.setSampleDataOnTrailingEdge(); - m_spi.setClockActiveLow(); + m_spi.setMode(SPI.Mode.kMode3); m_spi.setChipSelectActiveLow(); ByteBuffer transferBuffer = ByteBuffer.allocate(3); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXRS450_Gyro.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXRS450_Gyro.java index 5a826def27..e12d8b9270 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXRS450_Gyro.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXRS450_Gyro.java @@ -71,9 +71,7 @@ public class ADXRS450_Gyro implements Gyro, Sendable { } m_spi.setClockRate(3000000); - m_spi.setMSBFirst(); - m_spi.setSampleDataOnLeadingEdge(); - m_spi.setClockActiveHigh(); + m_spi.setMode(SPI.Mode.kMode0); m_spi.setChipSelectActiveLow(); if (m_simDevice == null) { diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/SPI.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/SPI.java index 2f073d20ae..f93a9f0b4e 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/SPI.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/SPI.java @@ -15,11 +15,11 @@ import java.nio.IntBuffer; /** Represents a SPI bus port. */ public class SPI implements AutoCloseable { public enum Port { - kOnboardCS0(0), - kOnboardCS1(1), - kOnboardCS2(2), - kOnboardCS3(3), - kMXP(4); + kOnboardCS0(SPIJNI.ONBOARD_CS0_PORT), + kOnboardCS1(SPIJNI.ONBOARD_CS0_PORT), + kOnboardCS2(SPIJNI.ONBOARD_CS0_PORT), + kOnboardCS3(SPIJNI.ONBOARD_CS0_PORT), + kMXP(SPIJNI.MXP_PORT); public final int value; @@ -28,10 +28,21 @@ public class SPI implements AutoCloseable { } } + public enum Mode { + kMode0(SPIJNI.SPI_MODE0), + kMode1(SPIJNI.SPI_MODE1), + kMode2(SPIJNI.SPI_MODE2), + kMode3(SPIJNI.SPI_MODE3); + + public final int value; + + Mode(int value) { + this.value = value; + } + } + private int m_port; - private int m_msbFirst; - private int m_clockIdleHigh; - private int m_sampleOnTrailing; + private int m_mode; /** * Constructor. @@ -39,10 +50,13 @@ public class SPI implements AutoCloseable { * @param port the physical SPI port */ public SPI(Port port) { - m_port = (byte) port.value; + m_port = port.value; SPIJNI.spiInitialize(m_port); + m_mode = 0; + SPIJNI.spiSetMode(m_port, m_mode); + HAL.report(tResourceType.kResourceType_SPI, port.value + 1); } @@ -72,55 +86,89 @@ public class SPI implements AutoCloseable { /** * Configure the order that bits are sent and received on the wire to be most significant bit * first. + * + * @deprecated Does not work, will be removed. */ + @Deprecated(since = "2023", forRemoval = true) public final void setMSBFirst() { - m_msbFirst = 1; - SPIJNI.spiSetOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + DriverStation.reportWarning("setMSBFirst not supported by roboRIO", false); } /** * Configure the order that bits are sent and received on the wire to be least significant bit * first. + * + * @deprecated Does not work, will be removed. */ + @Deprecated(since = "2023", forRemoval = true) public final void setLSBFirst() { - m_msbFirst = 0; - SPIJNI.spiSetOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + DriverStation.reportWarning("setLSBFirst not supported by roboRIO", false); } /** * Configure the clock output line to be active low. This is sometimes called clock polarity high * or clock idle high. + * + * @deprecated Use setMode() instead. */ + @Deprecated(since = "2023", forRemoval = true) public final void setClockActiveLow() { - m_clockIdleHigh = 1; - SPIJNI.spiSetOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + m_mode |= 1; + SPIJNI.spiSetMode(m_port, m_mode); } /** * Configure the clock output line to be active high. This is sometimes called clock polarity low * or clock idle low. + * + * @deprecated Use setMode() instead. */ + @Deprecated(since = "2023", forRemoval = true) public final void setClockActiveHigh() { - m_clockIdleHigh = 0; - SPIJNI.spiSetOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + m_mode &= 1; + SPIJNI.spiSetMode(m_port, m_mode); } /** * Configure that the data is stable on the leading edge and the data changes on the trailing * edge. + * + * @deprecated Use setMode() instead. */ + @Deprecated(since = "2023", forRemoval = true) public final void setSampleDataOnLeadingEdge() { - m_sampleOnTrailing = 0; - SPIJNI.spiSetOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + m_mode &= 2; + SPIJNI.spiSetMode(m_port, m_mode); } /** * Configure that the data is stable on the trailing edge and the data changes on the leading * edge. + * + * @deprecated Use setMode() instead. */ + @Deprecated(since = "2023", forRemoval = true) public final void setSampleDataOnTrailingEdge() { - m_sampleOnTrailing = 1; - SPIJNI.spiSetOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh); + m_mode |= 2; + SPIJNI.spiSetMode(m_port, m_mode); + } + + /** + * Sets the mode for the SPI device. + * + *

Mode 0 is Clock idle low, data sampled on rising edge. + * + *

Mode 1 is Clock idle low, data sampled on falling edge. + * + *

Mode 2 is Clock idle high, data sampled on falling edge. + * + *

Mode 3 is Clock idle high, data sampled on rising edge. + * + * @param mode The mode to set. + */ + public final void setMode(Mode mode) { + m_mode = mode.value & 0x3; + SPIJNI.spiSetMode(m_port, m_mode); } /** Configure the chip select line to be active high. */