/*----------------------------------------------------------------------------*/ /* 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 /** * 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 and maximum value is 500,000 Hz. * * @param hz The clock rate in Hertz. */ void SPI::SetClockRate(double hz) { int32_t retVal = 0; 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() { int32_t retVal = 0; 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() { int32_t retVal = 0; 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() { int32_t retVal = 0; 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() { int32_t retVal = 0; 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() { int32_t retVal = 0; 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() { int32_t retVal = 0; 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){ uint8_t* 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; }