Squashed 'third_party/allwpilib_2016/' content from commit 7f61816
Change-Id: If9d9245880859cdf580f5d7f77045135d0521ce7
git-subtree-dir: third_party/allwpilib_2016
git-subtree-split: 7f618166ed253a24629934fcf89c3decb0528a3b
diff --git a/wpilibc/Athena/src/SPI.cpp b/wpilibc/Athena/src/SPI.cpp
new file mode 100644
index 0000000..a470597
--- /dev/null
+++ b/wpilibc/Athena/src/SPI.cpp
@@ -0,0 +1,303 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. 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 $(WIND_BASE)/WPILib. */
+/*----------------------------------------------------------------------------*/
+
+#include "SPI.h"
+
+#include "WPIErrors.h"
+#include "HAL/Digital.hpp"
+
+#include <string.h>
+
+/**
+ * Constructor
+ *
+ * @param SPIport the physical SPI port
+ */
+SPI::SPI(Port SPIport) {
+ m_port = SPIport;
+ int32_t status = 0;
+ spiInitialize(m_port, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+ static int32_t instances = 0;
+ instances++;
+ HALReport(HALUsageReporting::kResourceType_SPI, instances);
+}
+
+/**
+ * Destructor.
+ */
+SPI::~SPI() { spiClose(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) { spiSetSpeed(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;
+ spiSetOpts(m_port, (int)m_msbFirst, (int)m_sampleOnTrailing,
+ (int)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;
+ spiSetOpts(m_port, (int)m_msbFirst, (int)m_sampleOnTrailing,
+ (int)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;
+ spiSetOpts(m_port, (int)m_msbFirst, (int)m_sampleOnTrailing,
+ (int)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;
+ spiSetOpts(m_port, (int)m_msbFirst, (int)m_sampleOnTrailing,
+ (int)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;
+ spiSetOpts(m_port, (int)m_msbFirst, (int)m_sampleOnTrailing,
+ (int)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;
+ spiSetOpts(m_port, (int)m_msbFirst, (int)m_sampleOnTrailing,
+ (int)m_clk_idle_high);
+}
+
+/**
+ * Configure the chip select line to be active high.
+ */
+void SPI::SetChipSelectActiveHigh() {
+ int32_t status = 0;
+ spiSetChipSelectActiveHigh(m_port, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Configure the chip select line to be active low.
+ */
+void SPI::SetChipSelectActiveLow() {
+ int32_t status = 0;
+ spiSetChipSelectActiveLow(m_port, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(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.
+ */
+int32_t SPI::Write(uint8_t* data, uint8_t size) {
+ int32_t retVal = 0;
+ retVal = spiWrite(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.
+ */
+int32_t SPI::Read(bool initiate, uint8_t* dataReceived, uint8_t size) {
+ int32_t retVal = 0;
+ if (initiate) {
+ auto dataToSend = new uint8_t[size];
+ memset(dataToSend, 0, size);
+ retVal = spiTransaction(m_port, dataToSend, dataReceived, size);
+ } else
+ retVal = spiRead(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
+ */
+int32_t SPI::Transaction(uint8_t* dataToSend, uint8_t* dataReceived,
+ uint8_t size) {
+ int32_t retVal = 0;
+ retVal = spiTransaction(m_port, dataToSend, dataReceived, size);
+ return retVal;
+}
+
+/**
+ * Initialize the accumulator.
+ *
+ * @param period Time between reads
+ * @param cmd SPI command to send to request data
+ * @param xfer_size SPI transfer size, in bytes
+ * @param valid_mask Mask to apply to received data for validity checking
+ * @param valid_data After valid_mask is applied, required matching value for
+ * validity checking
+ * @param data_shift Bit shift to apply to received data to get actual data
+ * value
+ * @param data_size Size (in bits) of data field
+ * @param is_signed Is data field signed?
+ * @param big_endian Is device big endian?
+ */
+void SPI::InitAccumulator(double period, uint32_t cmd, uint8_t xfer_size,
+ uint32_t valid_mask, uint32_t valid_value,
+ uint8_t data_shift, uint8_t data_size, bool is_signed,
+ bool big_endian) {
+ int32_t status = 0;
+ spiInitAccumulator(m_port, (uint32_t)(period * 1e6), cmd, xfer_size,
+ valid_mask, valid_value, data_shift, data_size, is_signed,
+ big_endian, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Frees the accumulator.
+ */
+void SPI::FreeAccumulator() {
+ int32_t status = 0;
+ spiFreeAccumulator(m_port, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Resets the accumulator to zero.
+ */
+void SPI::ResetAccumulator() {
+ int32_t status = 0;
+ spiResetAccumulator(m_port, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the center value of the accumulator.
+ *
+ * The center value is subtracted from each value before it is added to the accumulator. This
+ * is used for the center value of devices like gyros and accelerometers to make integration work
+ * and to take the device offset into account when integrating.
+ */
+void SPI::SetAccumulatorCenter(int32_t center) {
+ int32_t status = 0;
+ spiSetAccumulatorCenter(m_port, center, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the accumulator's deadband.
+ */
+void SPI::SetAccumulatorDeadband(int32_t deadband) {
+ int32_t status = 0;
+ spiSetAccumulatorDeadband(m_port, deadband, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Read the last value read by the accumulator engine.
+ */
+int32_t SPI::GetAccumulatorLastValue() const {
+ int32_t status = 0;
+ int32_t retVal = spiGetAccumulatorLastValue(m_port, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+ return retVal;
+}
+
+/**
+ * Read the accumulated value.
+ *
+ * @return The 64-bit value accumulated since the last Reset().
+ */
+int64_t SPI::GetAccumulatorValue() const {
+ int32_t status = 0;
+ int64_t retVal = spiGetAccumulatorValue(m_port, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+ return retVal;
+}
+
+/**
+ * Read the number of accumulated values.
+ *
+ * Read the count of the accumulated values since the accumulator was last Reset().
+ *
+ * @return The number of times samples from the channel were accumulated.
+ */
+uint32_t SPI::GetAccumulatorCount() const {
+ int32_t status = 0;
+ uint32_t retVal = spiGetAccumulatorCount(m_port, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+ return retVal;
+}
+
+/**
+ * Read the average of the accumulated value.
+ *
+ * @return The accumulated average value (value / count).
+ */
+double SPI::GetAccumulatorAverage() const {
+ int32_t status = 0;
+ double retVal = spiGetAccumulatorAverage(m_port, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+ return retVal;
+}
+
+/**
+ * Read the accumulated value and the number of accumulated values atomically.
+ *
+ * This function reads the value and count atomically.
+ * This can be used for averaging.
+ *
+ * @param value Pointer to the 64-bit accumulated output.
+ * @param count Pointer to the number of accumulation cycles.
+ */
+void SPI::GetAccumulatorOutput(int64_t &value, uint32_t &count) const {
+ int32_t status = 0;
+ spiGetAccumulatorOutput(m_port, &value, &count, &status);
+ wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}