//***************************************************************************** // // softssi.c - Driver for the SoftSSI. // // Copyright (c) 2010-2012 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 9453 of the Stellaris Firmware Development Package. // //***************************************************************************** //***************************************************************************** // //! \addtogroup softssi_api //! @{ // //***************************************************************************** #include "inc/hw_types.h" #include "driverlib/gpio.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "utils/softssi.h" //***************************************************************************** // // The states in the SoftSSI state machine. // //***************************************************************************** #define SOFTSSI_STATE_IDLE 0 #define SOFTSSI_STATE_START 1 #define SOFTSSI_STATE_IN 2 #define SOFTSSI_STATE_OUT 3 #define SOFTSSI_STATE_STOP1 4 #define SOFTSSI_STATE_STOP2 5 //***************************************************************************** // // The flags in the SoftSSI ucFlags structure member. // //***************************************************************************** #define SOFTSSI_FLAG_ENABLE 0x80 #define SOFTSSI_FLAG_SPH 0x02 #define SOFTSSI_FLAG_SPO 0x01 //***************************************************************************** // //! Sets the configuration of a SoftSSI module. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ucProtocol specifes the data transfer protocol. //! \param ucBits specifies the number of bits transferred per frame. //! //! This function configures the data format of a SoftSSI module. The //! \e ucProtocol parameter can be one of the following values: //! \b SOFTSSI_FRF_MOTO_MODE_0, \b SOFTSSI_FRF_MOTO_MODE_1, //! \b SOFTSSI_FRF_MOTO_MODE_2, or \b SOFTSSI_FRF_MOTO_MODE_3. These frame //! formats imply the following polarity and phase configurations: //! //!
//! Polarity Phase         Mode
//!   0       0   SOFTSSI_FRF_MOTO_MODE_0
//!   0       1   SOFTSSI_FRF_MOTO_MODE_1
//!   1       0   SOFTSSI_FRF_MOTO_MODE_2
//!   1       1   SOFTSSI_FRF_MOTO_MODE_3
//! 
//! //! The \e ucBits parameter defines the width of the data transfers, and can be //! a value between 4 and 16, inclusive. //! //! \return None. // //***************************************************************************** void SoftSSIConfigSet(tSoftSSI *pSSI, unsigned char ucProtocol, unsigned char ucBits) { // // See if a GPIO pin has been set for Fss. // if(pSSI->ulFssGPIO != 0) { // // Configure the Fss pin. // MAP_GPIOPinTypeGPIOOutput(pSSI->ulFssGPIO & 0xfffff000, (pSSI->ulFssGPIO & 0x00000fff) >> 2); // // Set the Fss pin high. // HWREG(pSSI->ulFssGPIO) = 255; } // // Configure the Clk pin. // MAP_GPIOPinTypeGPIOOutput(pSSI->ulClkGPIO & 0xfffff000, (pSSI->ulClkGPIO & 0x00000fff) >> 2); // // Set the Clk pin high or low based on the configured clock polarity. // if((ucProtocol & SOFTSSI_FLAG_SPO) == 0) { HWREG(pSSI->ulClkGPIO) = 0; } else { HWREG(pSSI->ulClkGPIO) = 255; } // // Configure the Tx pin and set it low. // MAP_GPIOPinTypeGPIOOutput(pSSI->ulTxGPIO & 0xfffff000, (pSSI->ulTxGPIO & 0x00000fff) >> 2); HWREG(pSSI->ulTxGPIO) = 0; // // See if a GPIO pin has been set for Rx. // if(pSSI->ulRxGPIO != 0) { // // Configure the Rx pin. // MAP_GPIOPinTypeGPIOInput(pSSI->ulRxGPIO & 0xfffff000, (pSSI->ulRxGPIO & 0x00000fff) >> 2); } // // Make sure that the transmit and receive FIFOs are empty. // pSSI->usTxBufferRead = 0; pSSI->usTxBufferWrite = 0; pSSI->usRxBufferRead = 0; pSSI->usRxBufferWrite = 0; // // Save the frame protocol. // pSSI->ucFlags = ucProtocol; // // Save the number of data bits. // pSSI->ucBits = ucBits; // // Since the FIFOs are empty, the transmit FIFO "interrupt" is asserted. // pSSI->ucIntStatus = SOFTSSI_TXFF; // // Reset the idle counter. // pSSI->ucIdleCount = 0; // // Disable the SoftSSI module. // pSSI->ucFlags &= ~(SOFTSSI_FLAG_ENABLE); // // Start the SoftSSI state machine in the idle state. // pSSI->ucState = SOFTSSI_STATE_IDLE; } //***************************************************************************** // //! Handles the assertion/deassertion of the transmit FIFO ``interrupt''. //! //! \param pSSI specifies the SoftSSI data structure. //! //! This function is used to determine when to assert or deassert the transmit //! FIFO ``interrupt''. //! //! \return None. // //***************************************************************************** static void SoftSSITxInt(tSoftSSI *pSSI) { unsigned short usTemp; // // Determine the number of words left in the transmit FIFO. // if(pSSI->usTxBufferRead > pSSI->usTxBufferWrite) { usTemp = (pSSI->usTxBufferLen + pSSI->usTxBufferWrite - pSSI->usTxBufferRead); } else { usTemp = pSSI->usTxBufferWrite - pSSI->usTxBufferRead; } // // If the transmit FIFO is now half full or less, generate a transmit FIFO // "interrupt". Otherwise, clear the transmit FIFO "interrupt". // if(usTemp <= (pSSI->usTxBufferLen / 2)) { pSSI->ucIntStatus |= SOFTSSI_TXFF; } else { pSSI->ucIntStatus &= ~(SOFTSSI_TXFF); } } //***************************************************************************** // //! Handles the assertion/deassertion of the receive FIFO ``interrupt''. //! //! \param pSSI specifies the SoftSSI data structure. //! //! This function is used to determine when to assert or deassert the receive //! FIFO ``interrupt''. //! //! \return None. // //***************************************************************************** static void SoftSSIRxInt(tSoftSSI *pSSI) { unsigned short usTemp; // // Determine the number of words in the receive FIFO. // if(pSSI->usRxBufferRead > pSSI->usRxBufferWrite) { usTemp = (pSSI->usRxBufferLen + pSSI->usRxBufferWrite - pSSI->usRxBufferRead); } else { usTemp = pSSI->usRxBufferWrite - pSSI->usRxBufferRead; } // // If the receive FIFO is now half full or more, generate a receive FIFO // "interrupt". Otherwise, clear the receive FIFO "interrupt". // if(usTemp >= (pSSI->usRxBufferLen / 2)) { pSSI->ucIntStatus |= SOFTSSI_RXFF; } else { pSSI->ucIntStatus &= ~(SOFTSSI_RXFF); } } //***************************************************************************** // //! Performs the periodic update of the SoftSSI module. //! //! \param pSSI specifies the SoftSSI data structure. //! //! This function performs the periodic, time-based updates to the SoftSSI //! module. The transmission and reception of data over the SoftSSI link is //! performed by the state machine in this function. //! //! This function must be called at twice the desired SoftSSI clock rate. For //! example, to run the SoftSSI clock at 10 KHz, this function must be called //! at a 20 KHz rate. //! //! \return None. // //***************************************************************************** void SoftSSITimerTick(tSoftSSI *pSSI) { unsigned short usTemp; // // Determine the current state of the state machine. // switch(pSSI->ucState) { // // The state machine is idle. // case SOFTSSI_STATE_IDLE: { // // See if the SoftSSI module is enabled and there is data in the // transmit FIFO. // if(((pSSI->ucFlags & SOFTSSI_FLAG_ENABLE) != 0) && (pSSI->usTxBufferRead != pSSI->usTxBufferWrite)) { // // Assert the Fss signal if it is configured. // if(pSSI->ulFssGPIO != 0) { HWREG(pSSI->ulFssGPIO) = 0; } // // Move to the start state. // pSSI->ucState = SOFTSSI_STATE_START; } // // Otherwise, see if there is data in the receive FIFO. // else if((pSSI->usRxBufferRead != pSSI->usRxBufferWrite) && (pSSI->ucIdleCount != 64)) { // // Increment the idle counter. // pSSI->ucIdleCount++; // // See if the idle counter has become large enough to trigger // a timeout "interrupt". // if(pSSI->ucIdleCount == 64) { // // Trigger the receive timeout "interrupt". // pSSI->ucIntStatus |= SOFTSSI_RXTO; } } // // This state has been handled. // break; } // // The start machine is in the transfer start state. // case SOFTSSI_STATE_START: { // // Get the next word to transfer from the transmit FIFO. // pSSI->usTxData = (pSSI->pusTxBuffer[pSSI->usTxBufferRead] << (16 - pSSI->ucBits)); // // Initialize the receive buffer to zero. // pSSI->usRxData = 0; // // Initialize the count of bits tranferred. // pSSI->ucCurrentBit = 0; // // Write the first bit of the transmit word to the Tx pin. // HWREG(pSSI->ulTxGPIO) = (pSSI->usTxData & 0x8000) ? 255 : 0; // // Shift to the next bit of the transmit word. // pSSI->usTxData <<= 1; // // If in SPI mode 1 or 3, then the Clk signal needs to be toggled. // if((pSSI->ucFlags & SOFTSSI_FLAG_SPH) != 0) { HWREG(pSSI->ulClkGPIO) ^= 255; } // // Move to the data input state. // pSSI->ucState = SOFTSSI_STATE_IN; // // This state has been handled. // break; } // // The state machine is in the data input state. // case SOFTSSI_STATE_IN: { // // Read the next bit from the Rx signal if it is configured. // if(pSSI->ulRxGPIO != 0) { pSSI->usRxData = ((pSSI->usRxData << 1) | (HWREG(pSSI->ulRxGPIO) ? 1 : 0)); } // // Toggle the Clk signal. // HWREG(pSSI->ulClkGPIO) ^= 255; // // Increment the number of bits transferred. // pSSI->ucCurrentBit++; // // See if the entire word has been transferred. // if(pSSI->ucCurrentBit != pSSI->ucBits) { // // There are more bits to transfer, so move to the data output // state. // pSSI->ucState = SOFTSSI_STATE_OUT; } else { // // Increment the transmit read pointer, removing the word that // was just transferred from the transmit FIFO. // pSSI->usTxBufferRead++; if(pSSI->usTxBufferRead == pSSI->usTxBufferLen) { pSSI->usTxBufferRead = 0; } // // See if a transmit FIFO "interrupt" needs to be asserted. // SoftSSITxInt(pSSI); // // Determine the new value for the receive FIFO write pointer. // usTemp = pSSI->usRxBufferWrite + 1; if(usTemp >= pSSI->usRxBufferLen) { usTemp = 0; } // // See if there is space in the receive FIFO for the word that // was just received. // if(usTemp == pSSI->usRxBufferRead) { // // The receive FIFO is full, so generate a receive FIFO // overrun "interrupt". // pSSI->ucIntStatus |= SOFTSSI_RXOR; } else { // // Store the new word into the receive FIFO. // pSSI->pusRxBuffer[pSSI->usRxBufferWrite] = pSSI->usRxData; // // Save the new receive FIFO write pointer. // pSSI->usRxBufferWrite = usTemp; // // See if a receive FIFO "interrupt" needs to be asserted. // SoftSSIRxInt(pSSI); } // // See if the next word should be transmitted immediately. // This will occur when there is data in the transmit FIFO, the // SoftSSI module is enabled, and the SoftSSI module is in SPI // mode 1 or 3. // if(((pSSI->ucFlags & SOFTSSI_FLAG_ENABLE) != 0) && ((pSSI->ucFlags & SOFTSSI_FLAG_SPH) != 0) && (pSSI->usTxBufferRead != pSSI->usTxBufferWrite)) { // // Get the next word to transfer from the transmit FIFO. // pSSI->usTxData = (pSSI->pusTxBuffer[pSSI->usTxBufferRead] << (16 - pSSI->ucBits)); // // Initialize the receive buffer to zero. // pSSI->usRxData = 0; // // Initialize the count of bits tranferred. // pSSI->ucCurrentBit = 0; // // Move to the data output state. // pSSI->ucState = SOFTSSI_STATE_OUT; } else { // // The next word should not be transmitted immediately, so // move to the first step of the stop state. // pSSI->ucState = SOFTSSI_STATE_STOP1; } } // // This state has been handled. // break; } // // The state machine is in the data output state. // case SOFTSSI_STATE_OUT: { // // Write the next bit of the transmit word to the Tx pin. // HWREG(pSSI->ulTxGPIO) = (pSSI->usTxData & 0x8000) ? 255 : 0; // // Toggle the Clk signal. // HWREG(pSSI->ulClkGPIO) ^= 255; // // Shift to the next bit of the transmit word. // pSSI->usTxData <<= 1; // // Move to the data input state. // pSSI->ucState = SOFTSSI_STATE_IN; // // This state has been handled. // break; } // // The state machine is in the first step of the stop state. // case SOFTSSI_STATE_STOP1: { // // Set the Tx pin low. // HWREG(pSSI->ulTxGPIO) = 0; // // If in SPI mode 1 or 3, then the Clk signal needs to be toggled. // if((pSSI->ucFlags & SOFTSSI_FLAG_SPH) == 0) { HWREG(pSSI->ulClkGPIO) ^= 255; } // // Move to the second step of the stop state. // pSSI->ucState = SOFTSSI_STATE_STOP2; // // This state has been handled. // break; } // // The state machine is in the second step of the stop state. // case SOFTSSI_STATE_STOP2: { // // Deassert the Fss signal if it is configured. // if(pSSI->ulFssGPIO != 0) { HWREG(pSSI->ulFssGPIO) = 255; } // // Move to the idle state. // pSSI->ucState = SOFTSSI_STATE_IDLE; // // Reset the idle counter. // pSSI->ucIdleCount = 0; // // See if the end of transfer "interrupt" should be generated. // if(pSSI->usTxBufferRead == pSSI->usTxBufferWrite) { pSSI->ucIntStatus |= SOFTSSI_TXEOT; } // // This state has been handled. // break; } } // // Call the "interrupt" callback while there are enabled "interrupts" // asserted. By calling in a loop until the "interrupts" are no longer // asserted, this mimics the behavior of a real hardware implementation of // the SSI peripheral. // while(((pSSI->ucIntStatus & pSSI->ucIntMask) != 0) && (pSSI->pfnIntCallback != 0)) { // // Call the callback function. // pSSI->pfnIntCallback(); } } //***************************************************************************** // //! Enables the SoftSSI module. //! //! \param pSSI specifies the SoftSSI data structure. //! //! This function enables operation of the SoftSSI module. The SoftSSI module //! must be configured before it is enabled. //! //! \return None. // //***************************************************************************** void SoftSSIEnable(tSoftSSI *pSSI) { // // Enable the SoftSSI module. // pSSI->ucFlags |= SOFTSSI_FLAG_ENABLE; } //***************************************************************************** // //! Disables the SoftSSI module. //! //! \param pSSI specifies the SoftSSI data structure. //! //! This function disables operation of the SoftSSI module. If a data transfer //! is in progress, it is finished before the module is fully disabled. //! //! \return None. // //***************************************************************************** void SoftSSIDisable(tSoftSSI *pSSI) { // // Disable the SoftSSI module. // pSSI->ucFlags &= ~(SOFTSSI_FLAG_ENABLE); } //***************************************************************************** // //! Enables individual SoftSSI ``interrupt'' sources. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ulIntFlags is a bit mask of the ``interrupt'' sources to be enabled. //! //! Enables the indicated SoftSSI ``interrupt'' sources. Only the sources that //! are enabled can be reflected to the callback function; disabled sources do //! not result in a callback. The \e ulIntFlags parameter can be any of the //! \b SOFTSSI_TXEOT, \b SOFTSSI_TXFF, \b SOFTSSI_RXFF, \b SOFTSSI_RXTO, or //! \b SOFTSSI_RXOR values. //! //! \return None. // //***************************************************************************** void SoftSSIIntEnable(tSoftSSI *pSSI, unsigned long ulIntFlags) { // // Enable the specified "interrupts". // pSSI->ucIntMask |= ulIntFlags; } //***************************************************************************** // //! Disables individual SoftSSI ``interrupt'' sources. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ulIntFlags is a bit mask of the ``interrupt'' sources to be //! disabled. //! //! Disables the indicated SoftSSI ``interrupt'' sources. The \e ulIntFlags //! parameter can be any of the \b SOFTSSI_TXEOT, \b SOFTSSI_TXFF, //! \b SOFTSSI_RXFF, \b SOFTSSI_RXTO, or \b SOFTSSI_RXOR values. //! //! \return None. // //***************************************************************************** void SoftSSIIntDisable(tSoftSSI *pSSI, unsigned long ulIntFlags) { // // Disable the specified "interrupts". // pSSI->ucIntMask &= ~(ulIntFlags); } //***************************************************************************** // //! Gets the current ``interrupt'' status. //! //! \param pSSI specifies the SoftSSI data structure. //! \param bMasked is \b false if the raw ``interrupt'' status is required or //! \b true if the masked ``interrupt'' status is required. //! //! This function returns the ``interrupt'' status for the SoftSSI module. //! Either the raw ``interrupt'' status or the status of ``interrupts'' that //! are allowed to reflect to the callback can be returned. //! //! \return The current ``interrupt'' status, enumerated as a bit field of //! \b SOFTSSI_TXEOT, \b SOFTSSI_TXFF, \b SOFTSSI_RXFF, \b SOFTSSI_RXTO, and //! \b SOFTSSI_RXOR. // //***************************************************************************** unsigned long SoftSSIIntStatus(tSoftSSI *pSSI, tBoolean bMasked) { // // Return either the "interrupt" status or the raw "interrupt" status as // requested. // if(bMasked) { return(pSSI->ucIntStatus & pSSI->ucIntMask); } else { return(pSSI->ucIntStatus); } } //***************************************************************************** // //! Clears SoftSSI ``interrupt'' sources. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ulIntFlags is a bit mask of the ``interrupt'' sources to be cleared. //! //! The specified SoftSSI ``interrupt'' sources are cleared so that they no //! longer assert. This function must be called in the ``interrupt'' handler //! to keep the ``interrupt'' from being recognized again immediately upon //! exit. The \e ulIntFlags parameter is the logical OR of any of the //! \b SOFTSSI_TXEOT, \b SOFTSSI_RXTO, and \b SOFTSSI_RXOR values. //! //! \return None. // //***************************************************************************** void SoftSSIIntClear(tSoftSSI *pSSI, unsigned long ulIntFlags) { // // Clear the requested "interrupt" sources. // pSSI->ucIntStatus &= ~(ulIntFlags) | SOFTSSI_TXFF | SOFTSSI_RXFF; } //***************************************************************************** // //! Determines if there is any data in the receive FIFO. //! //! \param pSSI specifies the SoftSSI data structure. //! //! This function determines if there is any data available to be read from the //! receive FIFO. //! //! \return Returns \b true if there is data in the receive FIFO or \b false //! if there is no data in the receive FIFO. // //***************************************************************************** tBoolean SoftSSIDataAvail(tSoftSSI *pSSI) { // // Return the availability of data. // return((pSSI->usRxBufferRead == pSSI->usRxBufferWrite) ? false : true); } //***************************************************************************** // //! Determines if there is any space in the transmit FIFO. //! //! \param pSSI specifies the SoftSSI data structure. //! //! This function determines if there is space available in the transmit FIFO. //! //! \return Returns \b true if there is space available in the transmit FIFO or //! \b false if there is no space available in the transmit FIFO. // //***************************************************************************** tBoolean SoftSSISpaceAvail(tSoftSSI *pSSI) { unsigned short usTemp; // // Determine the values of the write pointer once incremented. // usTemp = pSSI->usTxBufferWrite + 1; if(usTemp == pSSI->usTxBufferLen) { usTemp = 0; } // // Return the availability of space. // return((pSSI->usTxBufferRead == usTemp) ? false : true); } //***************************************************************************** // //! Puts a data element into the SoftSSI transmit FIFO. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ulData is the data to be transmitted over the SoftSSI interface. //! //! This function places the supplied data into the transmit FIFO of the //! specified SoftSSI module. //! //! \note The upper 32 - N bits of the \e ulData are discarded, where N is the //! data width as configured by SoftSSIConfigSet(). For example, if the //! interface is configured for 8-bit data width, the upper 24 bits of //! \e ulData are discarded. //! //! \return None. // //***************************************************************************** void SoftSSIDataPut(tSoftSSI *pSSI, unsigned long ulData) { unsigned short usTemp; // // Wait until there is space. // usTemp = pSSI->usTxBufferWrite + 1; if(usTemp == pSSI->usTxBufferLen) { usTemp = 0; } while(usTemp == *(volatile unsigned short *)(&(pSSI->usTxBufferRead))) { } // // Write the data to the SoftSSI. // pSSI->pusTxBuffer[pSSI->usTxBufferWrite] = ulData; pSSI->usTxBufferWrite = usTemp; // // See if a transmit FIFO "interrupt" needs to be cleared. // SoftSSITxInt(pSSI); } //***************************************************************************** // //! Puts a data element into the SoftSSI transmit FIFO. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ulData is the data to be transmitted over the SoftSSI interface. //! //! This function places the supplied data into the transmit FIFO of the //! specified SoftSSI module. If there is no space in the FIFO, then this //! function returns a zero. //! //! \note The upper 32 - N bits of the \e ulData are discarded, where N is the //! data width as configured by SoftSSIConfigSet(). For example, if the //! interface is configured for 8-bit data width, the upper 24 bits of //! \e ulData are discarded. //! //! \return Returns the number of elements written to the SSI transmit FIFO. // //***************************************************************************** long SoftSSIDataPutNonBlocking(tSoftSSI *pSSI, unsigned long ulData) { unsigned short usTemp; // // Determine the values of the write pointer once incremented. // usTemp = pSSI->usTxBufferWrite + 1; if(usTemp == pSSI->usTxBufferLen) { usTemp = 0; } // // Check for space to write. // if(usTemp != pSSI->usTxBufferRead) { pSSI->pusTxBuffer[pSSI->usTxBufferWrite] = ulData; pSSI->usTxBufferWrite = usTemp; SoftSSITxInt(pSSI); return(1); } else { return(0); } } //***************************************************************************** // //! Gets a data element from the SoftSSI receive FIFO. //! //! \param pSSI specifies the SoftSSI data structure. //! \param pulData is a pointer to a storage location for data that was //! received over the SoftSSI interface. //! //! This function gets received data from the receive FIFO of the specified //! SoftSSI module and places that data into the location specified by the //! \e pulData parameter. //! //! \note Only the lower N bits of the value written to \e pulData contain //! valid data, where N is the data width as configured by SoftSSIConfigSet(). //! For example, if the interface is configured for 8-bit data width, only the //! lower 8 bits of the value written to \e pulData contain valid data. //! //! \return None. // //***************************************************************************** void SoftSSIDataGet(tSoftSSI *pSSI, unsigned long *pulData) { // // Wait until there is data to be read. // while(pSSI->usRxBufferRead == *(volatile unsigned short *)(&(pSSI->usRxBufferWrite))) { } // // Read data from SoftSSI. // *pulData = pSSI->pusRxBuffer[pSSI->usRxBufferRead]; pSSI->usRxBufferRead++; if(pSSI->usRxBufferRead == pSSI->usRxBufferLen) { pSSI->usRxBufferRead = 0; } // // See if a receive FIFO "interrupt" needs to be cleared. // SoftSSIRxInt(pSSI); } //***************************************************************************** // //! Gets a data element from the SoftSSI receive FIFO. //! //! \param pSSI specifies the SoftSSI data structure. //! \param pulData is a pointer to a storage location for data that was //! received over the SoftSSI interface. //! //! This function gets received data from the receive FIFO of the specified //! SoftSSI module and places that data into the location specified by the //! \e ulData parameter. If there is no data in the FIFO, then this function //! returns a zero. //! //! \note Only the lower N bits of the value written to \e pulData contain //! valid data, where N is the data width as configured by SoftSSIConfigSet(). //! For example, if the interface is configured for 8-bit data width, only the //! lower 8 bits of the value written to \e pulData contain valid data. //! //! \return Returns the number of elements read from the SoftSSI receive FIFO. // //***************************************************************************** long SoftSSIDataGetNonBlocking(tSoftSSI *pSSI, unsigned long *pulData) { // // Check for data to read. // if(pSSI->usRxBufferRead != pSSI->usRxBufferWrite) { *pulData = pSSI->pusRxBuffer[pSSI->usRxBufferRead]; pSSI->usRxBufferRead++; if(pSSI->usRxBufferRead == pSSI->usRxBufferLen) { pSSI->usRxBufferRead = 0; } SoftSSIRxInt(pSSI); return(1); } else { return(0); } } //***************************************************************************** // //! Determines whether the SoftSSI transmitter is busy or not. //! //! \param pSSI specifies the SoftSSI data structure. //! //! Allows the caller to determine whether all transmitted bytes have cleared //! the transmitter. If \b false is returned, then the transmit FIFO is empty //! and all bits of the last transmitted word have left the shift register. //! //! \return Returns \b true if the SoftSSI is transmitting or \b false if all //! transmissions are complete. // //***************************************************************************** tBoolean SoftSSIBusy(tSoftSSI *pSSI) { // // Determine if the SSI is busy. // return(((pSSI->ucState == SOFTSSI_STATE_IDLE) && (((pSSI->ucFlags & SOFTSSI_FLAG_ENABLE) == 0) || (pSSI->usTxBufferRead == pSSI->usTxBufferWrite))) ? false : true); } //***************************************************************************** // //! Sets the callback used by the SoftSSI module. //! //! \param pSSI specifies the SoftSSI data structure. //! \param pfnCallback is a pointer to the callback function. //! //! This function sets the address of the callback function that is called when //! there is an ``interrupt'' produced by the SoftSSI module. //! //! \return None. // //***************************************************************************** void SoftSSICallbackSet(tSoftSSI *pSSI, void (*pfnCallback)(void)) { // // Save the callback function address. // pSSI->pfnIntCallback = pfnCallback; } //***************************************************************************** // //! Sets the GPIO pin to be used as the SoftSSI Fss signal. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ulBase is the base address of the GPIO module. //! \param ucPin is the bit-packed representation of the pin to use. //! //! This function sets the GPIO pin that is used for the SoftSSI Fss signal. //! If there is not a GPIO pin allocated for Fss, the SoftSSI module does not //! assert/deassert the Fss signal, leaving it to the application either to do //! manually or to not do at all if the slave device has Fss tied to ground. //! //! The pin is specified using a bit-packed byte, where bit 0 of the byte //! represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on. //! //! \return None. // //***************************************************************************** void SoftSSIFssGPIOSet(tSoftSSI *pSSI, unsigned long ulBase, unsigned char ucPin) { // // Save the base address and pin for the Fss signal. // if(ulBase == 0) { pSSI->ulFssGPIO = 0; } else { pSSI->ulFssGPIO = ulBase + (ucPin << 2); } } //***************************************************************************** // //! Sets the GPIO pin to be used as the SoftSSI Clk signal. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ulBase is the base address of the GPIO module. //! \param ucPin is the bit-packed representation of the pin to use. //! //! This function sets the GPIO pin that is used for the SoftSSI Clk signal. //! //! The pin is specified using a bit-packed byte, where bit 0 of the byte //! represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on. //! //! \return None. // //***************************************************************************** void SoftSSIClkGPIOSet(tSoftSSI *pSSI, unsigned long ulBase, unsigned char ucPin) { // // Save the base address and pin for the Clk signal. // pSSI->ulClkGPIO = ulBase + (ucPin << 2); } //***************************************************************************** // //! Sets the GPIO pin to be used as the SoftSSI Tx signal. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ulBase is the base address of the GPIO module. //! \param ucPin is the bit-packed representation of the pin to use. //! //! This function sets the GPIO pin that is used for the SoftSSI Tx signal. //! //! The pin is specified using a bit-packed byte, where bit 0 of the byte //! represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on. //! //! \return None. // //***************************************************************************** void SoftSSITxGPIOSet(tSoftSSI *pSSI, unsigned long ulBase, unsigned char ucPin) { // // Save the base address and pin for the Tx signal. // pSSI->ulTxGPIO = ulBase + (ucPin << 2); } //***************************************************************************** // //! Sets the GPIO pin to be used as the SoftSSI Rx signal. //! //! \param pSSI specifies the SoftSSI data structure. //! \param ulBase is the base address of the GPIO module. //! \param ucPin is the bit-packed representation of the pin to use. //! //! This function sets the GPIO pin that is used for the SoftSSI Rx signal. If //! there is not a GPIO pin allocated for Rx, the SoftSSI module does not read //! data from the slave device. //! //! The pin is specified using a bit-packed byte, where bit 0 of the byte //! represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on. //! //! \return None. // //***************************************************************************** void SoftSSIRxGPIOSet(tSoftSSI *pSSI, unsigned long ulBase, unsigned char ucPin) { // // Save the base address and pin for the Rx signal. // if(ulBase == 0) { pSSI->ulRxGPIO = 0; } else { pSSI->ulRxGPIO = ulBase + (ucPin << 2); } } //***************************************************************************** // //! Sets the transmit FIFO buffer for a SoftSSI module. //! //! \param pSSI specifies the SoftSSI data structure. //! \param pusTxBuffer is the address of the transmit FIFO buffer. //! \param usLen is the size, in 16-bit half-words, of the transmit FIFO //! buffer. //! //! This function sets the address and size of the transmit FIFO buffer and //! also resets the read and write pointers, marking the transmit FIFO as //! empty. //! //! \return None. // //***************************************************************************** void SoftSSITxBufferSet(tSoftSSI *pSSI, unsigned short *pusTxBuffer, unsigned short usLen) { // // Save the transmit FIFO buffer address and length. // pSSI->pusTxBuffer = pusTxBuffer; pSSI->usTxBufferLen = usLen; // // Reset the transmit FIFO read and write pointers. // pSSI->usTxBufferRead = 0; pSSI->usTxBufferWrite = 0; } //***************************************************************************** // //! Sets the receive FIFO buffer for a SoftSSI module. //! //! \param pSSI specifies the SoftSSI data structure. //! \param pusRxBuffer is the address of the receive FIFO buffer. //! \param usLen is the size, in 16-bit half-words, of the receive FIFO buffer. //! //! This function sets the address and size of the receive FIFO buffer and also //! resets the read and write pointers, marking the receive FIFO as empty. //! When the buffer pointer and length are configured as zero, all data //! received from the slave device is discarded. This capability is useful //! when there is no GPIO pin allocated for the Rx signal. //! //! \return None. // //***************************************************************************** void SoftSSIRxBufferSet(tSoftSSI *pSSI, unsigned short *pusRxBuffer, unsigned short usLen) { // // Save the receive FIFO buffer address and length. // pSSI->pusRxBuffer = pusRxBuffer; pSSI->usRxBufferLen = usLen; // // Reset the receive FIFO read and write pointers. // pSSI->usRxBufferRead = 0; pSSI->usRxBufferWrite = 0; } //***************************************************************************** // // Close the Doxygen group. //! @} // //*****************************************************************************