Added isSPI3w API to DevSPI

Fork of X_NUCLEO_COMMON by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DevSPI.h Source File

DevSPI.h

Go to the documentation of this file.
00001 /**
00002  ******************************************************************************
00003  * @file    DevSPI.h
00004  * @author  AST / Software Platforms and Cloud / EST
00005  * @version V1.2.1
00006  * @date    19-February-2016
00007  * @brief   Header file for a special SPI class DevSPI which provides some
00008  *          helper functions for on-board communication.
00009  ******************************************************************************
00010  * @attention
00011  *
00012  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
00013  *
00014  * Redistribution and use in source and binary forms, with or without modification,
00015  * are permitted provided that the following conditions are met:
00016  *   1. Redistributions of source code must retain the above copyright notice,
00017  *      this list of conditions and the following disclaimer.
00018  *   2. Redistributions in binary form must reproduce the above copyright notice,
00019  *      this list of conditions and the following disclaimer in the documentation
00020  *      and/or other materials provided with the distribution.
00021  *   3. Neither the name of STMicroelectronics nor the names of its contributors
00022  *      may be used to endorse or promote products derived from this software
00023  *      without specific prior written permission.
00024  *
00025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00028  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00029  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00030  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00031  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00032  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00033  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  ******************************************************************************
00037  */
00038 
00039 /* Define to prevent from recursive inclusion --------------------------------*/
00040 #ifndef __DEV_SPI_H
00041 #define __DEV_SPI_H
00042 
00043 /* Includes ------------------------------------------------------------------*/
00044 #include "mbed.h"
00045 
00046 /* Macros --------------------------------------------------------------------*/
00047 #if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) /* GCC */ || \
00048     (defined(G_BYTE_ORDER) && (G_BYTE_ORDER == G_BIG_ENDIAN)) /* IAR */ || \
00049     (defined(__BIG_ENDIAN)) /* ARM */
00050 #define __DEV_SPI_BIG_ENDIAN
00051 #endif
00052 
00053 /* Classes -------------------------------------------------------------------*/
00054 /** Helper class DevSPI providing functions for synchronous SPI communication
00055  *  common for a series of SPI devices.
00056  */
00057 class DevSPI : public SPI
00058 {
00059  public:
00060     /*
00061      * Create a DevSPI interface.
00062      * @param mosi pin name of the MOSI pin of the SPI device to be used for communication.
00063      * @param miso pin name of the MISO pin of the SPI device to be used for communication.
00064      * @param sclk pin name of the SCLK pin of the SPI device to be used for communication.
00065      */
00066     DevSPI(PinName mosi, PinName miso, PinName sclk) : SPI(mosi, miso, sclk)
00067     {
00068         if (miso == NC) is_spi3w = true;
00069         else is_spi3w = false;        
00070         /* Set default configuration. */
00071         setup(8, 3, 1E6);
00072     }
00073 
00074     /*
00075      * Setup the spi.
00076      * Typically:
00077      *  + 8 bit data;
00078      *  + high steady state clock;
00079      *  + second edge capture;
00080      *  + 1MHz clock rate.
00081      *
00082      * @param bits         Number of bits per SPI frame (4 - 16)
00083      * @param mode         Clock polarity and phase mode (0 - 3)
00084      * @param frequency_hz SCLK frequency in hz (default = 1MHz)
00085      *
00086      * @code
00087      * mode | POL PHA
00088      * -----+--------
00089      *   0  |  0   0
00090      *   1  |  0   1
00091      *   2  |  1   0
00092      *   3  |  1   1
00093      * @endcode
00094      */
00095     void setup(int bits, int mode = 0, int frequency_hz = 1E6)
00096     {
00097         /* Set given configuration. */
00098         format(bits, mode);
00099         frequency(frequency_hz);
00100     }
00101 
00102     /**
00103      * @brief      Writes a buffer to the SPI peripheral device in 8-bit data mode 
00104      *             using synchronous SPI communication.
00105      * @param[in]  pBuffer pointer to the buffer of data to send.
00106      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00107      * @param[in]  NumBytesToWrite number of bytes to write.
00108      * @retval     0 if ok.
00109      * @retval     -1 if data format error.
00110      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00111      *             before calling this function and to enable them again after.
00112      */
00113     int spi_write(uint8_t* pBuffer, DigitalOut &ssel, uint16_t NumBytesToWrite)
00114     {
00115     /* Check data format */
00116     if(_bits != 8) return -1;
00117 
00118         /* Select the chip. */
00119         ssel = 0;
00120         
00121         /* Write data. */
00122     for (int i = 0; i < NumBytesToWrite; i++) {
00123             write(pBuffer[i]);
00124     }
00125 
00126         /* Unselect the chip. */
00127         ssel = 1;
00128 
00129         return 0;
00130     }
00131 
00132     /**
00133      * @brief      Reads a buffer from the SPI peripheral device in 8-bit data mode 
00134      *             using synchronous SPI communication.
00135      * @param[out] pBuffer pointer to the buffer to read data into.
00136      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00137      * @param[in]  NumBytesToRead number of bytes to read.
00138      * @retval     0 if ok.
00139      * @retval     -1 if data format error.
00140      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00141      *             before calling this function and to enable them again after.
00142      */
00143     int spi_read(uint8_t* pBuffer, DigitalOut &ssel, uint16_t NumBytesToRead)
00144     {
00145     /* Check data format */
00146     if(_bits != 8) return -1;
00147 
00148         /* Select the chip. */
00149         ssel = 0;
00150         
00151         /* Read data. */
00152     for (int i = 0; i < NumBytesToRead; i++) {
00153         pBuffer[i] = write(0);
00154     }
00155 
00156         /* Unselect the chip. */
00157         ssel = 1;
00158 
00159         return 0;
00160     }
00161 
00162     /**
00163      * @brief      Reads and write a buffer from/to the SPI peripheral device at the same time 
00164      *             in 8-bit data mode using synchronous SPI communication.
00165      * @param[out] pBufferToRead pointer to the buffer to read data into.
00166      * @param[in]  pBufferToWrite pointer to the buffer of data to send.
00167      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00168      * @param[in]  NumBytes number of bytes to read and write.
00169      * @retval     0 if ok.
00170      * @retval     -1 if data format error.
00171      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00172      *             before calling this function and to enable them again after.
00173      */
00174     int spi_read_write(uint8_t* pBufferToRead, uint8_t* pBufferToWrite, DigitalOut &ssel, uint16_t NumBytes)
00175     {
00176     /* Check data format */
00177     if(_bits != 8) return -1;
00178 
00179         /* Select the chip. */
00180         ssel = 0;
00181         
00182         /* Read and write data at the same time. */
00183     for (int i = 0; i < NumBytes; i++) {
00184             pBufferToRead[i] = write(pBufferToWrite[i]);
00185     }
00186 
00187         /* Unselect the chip. */
00188         ssel = 1;
00189 
00190         return 0;
00191     }
00192 
00193     /**
00194      * @brief      Writes a buffer to the SPI peripheral device in 16-bit data mode 
00195      *             using synchronous SPI communication.
00196      * @param[in]  pBuffer pointer to the buffer of data to send.
00197      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00198      * @param[in]  NumValuesToWrite number of 16-bit values to write.
00199      * @retval     0 if ok.
00200      * @retval     -1 if data format error.
00201      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00202      *             before calling this function and to enable them again after.
00203      * @note       In order to guarantee this method to work correctly you have to
00204      *             pass buffers which are correctly aligned.
00205      */
00206     int spi_write(uint16_t* pBuffer, DigitalOut &ssel, uint16_t NumValuesToWrite)
00207     {
00208     /* Check data format */
00209     if(_bits != 16) return -1;
00210 
00211         /* Select the chip. */
00212         ssel = 0;
00213         
00214         /* Write data. */
00215     for (int i = 0; i < NumValuesToWrite; i++) {
00216         write(htons(pBuffer[i]));
00217     }
00218 
00219         /* Unselect the chip. */
00220         ssel = 1;
00221 
00222         return 0;
00223     }
00224 
00225     /**
00226      * @brief      Reads a buffer from the SPI peripheral device in 16-bit data mode 
00227      *             using synchronous SPI communication.
00228      * @param[out] pBuffer pointer to the buffer to read data into.
00229      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00230      * @param[in]  NumValuesToRead number of 16-bit values to read.
00231      * @retval     0 if ok.
00232      * @retval     -1 if data format error.
00233      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00234      *             before calling this function and to enable them again after.
00235      * @note       In order to guarantee this method to work correctly you have to
00236      *             pass buffers which are correctly aligned.
00237      */
00238     int spi_read(uint16_t* pBuffer, DigitalOut &ssel, uint16_t NumValuesToRead)
00239     {
00240     /* Check data format */
00241     if(_bits != 16) return -1;
00242 
00243         /* Select the chip. */
00244         ssel = 0;
00245         
00246         /* Read data. */
00247     for (int i = 0; i < NumValuesToRead; i++) {
00248         pBuffer[i] = ntohs((uint16_t)write(0));
00249     }
00250 
00251         /* Unselect the chip. */
00252         ssel = 1;
00253 
00254         return 0;
00255     }
00256 
00257     /**
00258      * @brief      Reads and write a buffer from/to the SPI peripheral device at the same time 
00259      *             in 16-bit data mode using synchronous SPI communication.
00260      * @param[out] pBufferToRead pointer to the buffer to read data into.
00261      * @param[in]  pBufferToWrite pointer to the buffer of data to send.
00262      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00263      * @param[in]  NumValues number of 16-bit values to read and write.
00264      * @retval     0 if ok.
00265      * @retval     -1 if data format error.
00266      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00267      *             before calling this function and to enable them again after.
00268      * @note       In order to guarantee this method to work correctly you have to
00269      *             pass buffers which are correctly aligned.
00270      */
00271     int spi_read_write(uint16_t* pBufferToRead, uint16_t* pBufferToWrite, DigitalOut &ssel, uint16_t NumValues)
00272     {
00273     /* Check data format */
00274     if(_bits != 16) return -1;
00275 
00276     /* Select the chip. */
00277         ssel = 0;
00278         
00279         /* Read and write data at the same time. */
00280     for (int i = 0; i < NumValues; i++) {
00281         pBufferToRead[i] = ntohs((uint16_t)write(htons(pBufferToWrite[i])));
00282     }
00283 
00284         /* Unselect the chip. */
00285         ssel = 1;
00286 
00287         return 0;
00288     }
00289 
00290     inline bool isSPI3w() {
00291         return is_spi3w;
00292     }
00293     
00294 protected:
00295     inline uint16_t htons(uint16_t x) {
00296 #ifndef __DEV_SPI_BIG_ENDIAN
00297     return (((x)<<8)|((x)>>8));
00298 #else  // __DEV_SPI_BIG_ENDIAN
00299     return (x);
00300 #endif // __DEV_SPI_BIG_ENDIAN
00301     }
00302 
00303     inline uint16_t ntohs(uint16_t x) {
00304     return htons(x);
00305     }
00306 };
00307 
00308 #endif /* __DEV_SPI_H */