Added ahal
This is a formatted copy of WPILib's default user-visible C++ API, with
a bit of completely unnecessary functionality stripped out. Most of the
stripping so far is only related to weird threading decisions.
Change-Id: Icbfd949b48cd115561862cb909bcc572aba0e753
diff --git a/frc971/wpilib/ahal/SPI.cc b/frc971/wpilib/ahal/SPI.cc
new file mode 100644
index 0000000..5e18fc1
--- /dev/null
+++ b/frc971/wpilib/ahal/SPI.cc
@@ -0,0 +1,176 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008-2017. 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 "HAL/SPI.h"
+#include "frc971/wpilib/ahal/SPI.h"
+
+#include <cstring>
+
+#include "HAL/HAL.h"
+#include "llvm/SmallVector.h"
+
+using namespace frc;
+
+#define HAL_FATAL_WITH_STATUS(status)
+
+/**
+ * Constructor
+ *
+ * @param SPIport the physical SPI port
+ */
+SPI::SPI(Port SPIport) {
+#ifdef WPILIB2017
+ m_port = SPIport;
+#else
+ m_port = static_cast<HAL_SPIPort>(SPIport);
+#endif
+ int32_t status = 0;
+ HAL_InitializeSPI(m_port, &status);
+ HAL_FATAL_WITH_STATUS(status);
+
+ static int instances = 0;
+ instances++;
+ HAL_Report(HALUsageReporting::kResourceType_SPI, instances);
+}
+
+/**
+ * Destructor.
+ */
+SPI::~SPI() { HAL_CloseSPI(m_port); }
+
+/**
+ * Configure the rate of the generated clock signal.
+ *
+ * The default value is 500,000Hz.
+ * The maximum value is 4,000,000Hz.
+ *
+ * @param hz The clock rate in Hertz.
+ */
+void SPI::SetClockRate(double hz) { HAL_SetSPISpeed(m_port, hz); }
+
+/**
+ * Configure the order that bits are sent and received on the wire
+ * to be most significant bit first.
+ */
+void SPI::SetMSBFirst() {
+ m_msbFirst = true;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clk_idle_high);
+}
+
+/**
+ * Configure the order that bits are sent and received on the wire
+ * to be least significant bit first.
+ */
+void SPI::SetLSBFirst() {
+ m_msbFirst = false;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clk_idle_high);
+}
+
+/**
+ * Configure that the data is stable on the falling edge and the data
+ * changes on the rising edge.
+ */
+void SPI::SetSampleDataOnFalling() {
+ m_sampleOnTrailing = true;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clk_idle_high);
+}
+
+/**
+ * Configure that the data is stable on the rising edge and the data
+ * changes on the falling edge.
+ */
+void SPI::SetSampleDataOnRising() {
+ m_sampleOnTrailing = false;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clk_idle_high);
+}
+
+/**
+ * Configure the clock output line to be active low.
+ * This is sometimes called clock polarity high or clock idle high.
+ */
+void SPI::SetClockActiveLow() {
+ m_clk_idle_high = true;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clk_idle_high);
+}
+
+/**
+ * Configure the clock output line to be active high.
+ * This is sometimes called clock polarity low or clock idle low.
+ */
+void SPI::SetClockActiveHigh() {
+ m_clk_idle_high = false;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clk_idle_high);
+}
+
+/**
+ * Configure the chip select line to be active high.
+ */
+void SPI::SetChipSelectActiveHigh() {
+ int32_t status = 0;
+ HAL_SetSPIChipSelectActiveHigh(m_port, &status);
+ HAL_FATAL_WITH_STATUS(status);
+}
+
+/**
+ * Configure the chip select line to be active low.
+ */
+void SPI::SetChipSelectActiveLow() {
+ int32_t status = 0;
+ HAL_SetSPIChipSelectActiveLow(m_port, &status);
+ HAL_FATAL_WITH_STATUS(status);
+}
+
+/**
+ * Write data to the slave device. Blocks until there is space in the
+ * output FIFO.
+ *
+ * If not running in output only mode, also saves the data received
+ * on the MISO input during the transfer into the receive FIFO.
+ */
+int SPI::Write(uint8_t *data, int size) {
+ int retVal = 0;
+ retVal = HAL_WriteSPI(m_port, data, size);
+ return retVal;
+}
+
+/**
+ * Read a word from the receive FIFO.
+ *
+ * Waits for the current transfer to complete if the receive FIFO is empty.
+ *
+ * If the receive FIFO is empty, there is no active transfer, and initiate
+ * is false, errors.
+ *
+ * @param initiate If true, this function pushes "0" into the transmit buffer
+ * and initiates a transfer. If false, this function assumes
+ * that data is already in the receive FIFO from a previous
+ * write.
+ */
+int SPI::Read(bool initiate, uint8_t *dataReceived, int size) {
+ int retVal = 0;
+ if (initiate) {
+ llvm::SmallVector<uint8_t, 32> dataToSend;
+ dataToSend.resize(size);
+ retVal = HAL_TransactionSPI(m_port, dataToSend.data(), dataReceived, size);
+ } else {
+ retVal = HAL_ReadSPI(m_port, dataReceived, size);
+ }
+ return retVal;
+}
+
+/**
+ * Perform a simultaneous read/write transaction with the device
+ *
+ * @param dataToSend The data to be written out to the device
+ * @param dataReceived Buffer to receive data from the device
+ * @param size The length of the transaction, in bytes
+ */
+int SPI::Transaction(uint8_t *dataToSend, uint8_t *dataReceived, int size) {
+ int retVal = 0;
+ retVal = HAL_TransactionSPI(m_port, dataToSend, dataReceived, size);
+ return retVal;
+}