Shih-Ho Hsieh / XYZ_sensor_Platform_SPI

Fork of XYZ_sensor_Platform by Shih-Ho Hsieh

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         /* Set default configuration. */
00069         setup(8, 3, 1E6);
00070     }
00071 
00072     /*
00073      * Setup the spi.
00074      * Typically:
00075      *  + 8 bit data;
00076      *  + high steady state clock;
00077      *  + second edge capture;
00078      *  + 1MHz clock rate.
00079      *
00080      * @param bits         Number of bits per SPI frame (4 - 16)
00081      * @param mode         Clock polarity and phase mode (0 - 3)
00082      * @param frequency_hz SCLK frequency in hz (default = 1MHz)
00083      *
00084      * @code
00085      * mode | POL PHA
00086      * -----+--------
00087      *   0  |  0   0
00088      *   1  |  0   1
00089      *   2  |  1   0
00090      *   3  |  1   1
00091      * @endcode
00092      */
00093     void setup(int bits, int mode = 0, int frequency_hz = 1E6)
00094     {
00095         /* Set given configuration. */
00096         format(bits, mode);
00097         frequency(frequency_hz);
00098     }
00099 
00100     /**
00101      * @brief      Writes a buffer to the SPI peripheral device in 8-bit data mode 
00102      *             using synchronous SPI communication.
00103      * @param[in]  pBuffer pointer to the buffer of data to send.
00104      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00105      * @param[in]  NumBytesToWrite number of bytes to write.
00106      * @retval     0 if ok.
00107      * @retval     -1 if data format error.
00108      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00109      *             before calling this function and to enable them again after.
00110      */
00111     int spi_write(uint8_t* pBuffer, DigitalOut &ssel, uint16_t NumBytesToWrite)
00112     {
00113     /* Check data format */
00114     if(_bits != 8) return -1;
00115 
00116         /* Select the chip. */
00117         ssel = 0;
00118         
00119         /* Write data. */
00120     for (int i = 0; i < NumBytesToWrite; i++) {
00121             write(pBuffer[i]);
00122     }
00123 
00124         /* Unselect the chip. */
00125         ssel = 1;
00126 
00127         return 0;
00128     }
00129 
00130 
00131     /**
00132      * @brief      Reads a buffer from the SPI peripheral device in 8-bit data mode 
00133      *             using synchronous SPI communication.
00134      * @param[out] pBuffer pointer to the buffer to read data into.
00135      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00136      * @param[in]  NumBytesToRead number of bytes to read.
00137      * @retval     0 if ok.
00138      * @retval     -1 if data format error.
00139      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00140      *             before calling this function and to enable them again after.
00141      */
00142     int spi_read(uint8_t* pBuffer, DigitalOut &ssel, uint16_t NumBytesToRead)
00143     {
00144     /* Check data format */
00145     if(_bits != 8) return -1;
00146 
00147         /* Select the chip. */
00148         ssel = 0;
00149         
00150         /* Read data. */
00151     for (int i = 0; i < NumBytesToRead; i++) {
00152         pBuffer[i] = write(0);
00153     }
00154 
00155         /* Unselect the chip. */
00156         ssel = 1;
00157 
00158         return 0;
00159     }
00160 
00161     /**
00162      * @brief      Writes a buffer to the SPI peripheral device in 8-bit data mode 
00163      *             using synchronous SPI communication.
00164      * @param[in]  pBuffer pointer to the buffer of data to send.
00165      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00166      * @param[in]  NumBytesToWrite number of bytes to write.
00167      * @retval     0 if ok.
00168      * @retval     -1 if data format error.
00169      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00170      *             before calling this function and to enable them again after.
00171      */
00172     int spi_write_reg(uint8_t* pBuffer, uint8_t regAddr, DigitalInOut &ssel, uint16_t NumBytes)
00173     {
00174     /* Check data format */
00175     if(_bits != 8) return -1;
00176 
00177         /* Select the chip. */
00178         ssel = 0;
00179         
00180         /* Write data. */
00181         /*
00182         uint8_t *pData = new uint8_t [NumBytes+1];
00183         pData[0] = regAddr;
00184         for (int i = 0; i < NumBytes; i++) {
00185             pData[i+1] = pBuffer[i];
00186         }
00187         SPI::write((char *)pData, NumBytes+1, NULL, 0);
00188         
00189         */
00190         write(regAddr);
00191         for (int i = 0; i < NumBytes; i++) {
00192             write(pBuffer[i]);
00193         }
00194         int i = 1;
00195         while(i++<10);
00196 
00197         /* Unselect the chip. */
00198         ssel = 1;
00199         
00200 
00201         return 0;
00202     }
00203 
00204     /**
00205      * @brief      Reads a buffer from the SPI peripheral device
00206      *             in 8-bit data mode using synchronous SPI communication.
00207      * @param[out] pBufferToRead pointer to the buffer to read data into.
00208      * @param[in]  regAddr register address to send.
00209      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00210      * @param[in]  NumBytes number of bytes to read.
00211      * @retval     0 if ok.
00212      * @retval     -1 if data format error.
00213      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00214      *             before calling this function and to enable them again after.
00215      */
00216     int spi_read_reg(uint8_t* pBuffer, uint8_t regAddr, DigitalInOut &ssel, uint16_t NumBytes)
00217     {
00218     /* Check data format */
00219     if(_bits != 8) return -1;
00220 
00221         /* Select the chip. */
00222         ssel = 0;
00223         
00224         /* Read and write data at the same time. */
00225         /*
00226         char *pData = new char [NumBytes+1];
00227         SPI::write((char *)&regAddr, 1, pData, NumBytes+1);
00228         for(int i = 1; i < NumBytes; i++)
00229         {
00230             pBuffer[i] = pData[i+1];
00231         }
00232         */
00233         
00234         write(regAddr);
00235         for (int i = 0; i < NumBytes; i++) {
00236             pBuffer[i] = write(0);
00237         }
00238 
00239         /* Unselect the chip. */
00240         ssel = 1;
00241         
00242 
00243         return 0;
00244     }
00245 
00246     /**
00247      * @brief      Reads and write a buffer from/to the SPI peripheral device at the same time 
00248      *             in 8-bit data mode using synchronous SPI communication.
00249      * @param[out] pBufferToRead pointer to the buffer to read data into.
00250      * @param[in]  pBufferToWrite pointer to the buffer of data to send.
00251      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00252      * @param[in]  NumBytes number of bytes to read and write.
00253      * @retval     0 if ok.
00254      * @retval     -1 if data format error.
00255      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00256      *             before calling this function and to enable them again after.
00257      */
00258     int spi_read_write(uint8_t* pBufferToRead, uint8_t* pBufferToWrite, DigitalOut &ssel, uint16_t NumBytes)
00259     {
00260     /* Check data format */
00261     if(_bits != 8) return -1;
00262 
00263         /* Select the chip. */
00264         ssel = 0;
00265         
00266         /* Read and write data at the same time. */
00267     for (int i = 0; i < NumBytes; i++) {
00268             pBufferToRead[i] = write(pBufferToWrite[i]);
00269     }
00270 
00271         /* Unselect the chip. */
00272         ssel = 1;
00273 
00274         return 0;
00275     }
00276     
00277     /**
00278      * @brief      Writes a buffer to the SPI peripheral device in 16-bit data mode 
00279      *             using synchronous SPI communication.
00280      * @param[in]  pBuffer pointer to the buffer of data to send.
00281      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00282      * @param[in]  NumValuesToWrite number of 16-bit values to write.
00283      * @retval     0 if ok.
00284      * @retval     -1 if data format error.
00285      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00286      *             before calling this function and to enable them again after.
00287      * @note       In order to guarantee this method to work correctly you have to
00288      *             pass buffers which are correctly aligned.
00289      */
00290     int spi_write(uint16_t* pBuffer, DigitalOut &ssel, uint16_t NumValuesToWrite)
00291     {
00292     /* Check data format */
00293     if(_bits != 16) return -1;
00294 
00295         /* Select the chip. */
00296         ssel = 0;
00297         
00298         /* Write data. */
00299     for (int i = 0; i < NumValuesToWrite; i++) {
00300         write(htons(pBuffer[i]));
00301     }
00302 
00303         /* Unselect the chip. */
00304         ssel = 1;
00305 
00306         return 0;
00307     }
00308 
00309     /**
00310      * @brief      Reads a buffer from the SPI peripheral device in 16-bit data mode 
00311      *             using synchronous SPI communication.
00312      * @param[out] pBuffer pointer to the buffer to read data into.
00313      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00314      * @param[in]  NumValuesToRead number of 16-bit values to read.
00315      * @retval     0 if ok.
00316      * @retval     -1 if data format error.
00317      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00318      *             before calling this function and to enable them again after.
00319      * @note       In order to guarantee this method to work correctly you have to
00320      *             pass buffers which are correctly aligned.
00321      */
00322     int spi_read(uint16_t* pBuffer, DigitalOut &ssel, uint16_t NumValuesToRead)
00323     {
00324     /* Check data format */
00325     if(_bits != 16) return -1;
00326 
00327         /* Select the chip. */
00328         ssel = 0;
00329         
00330         /* Read data. */
00331     for (int i = 0; i < NumValuesToRead; i++) {
00332         pBuffer[i] = ntohs((uint16_t)write(0));
00333     }
00334 
00335         /* Unselect the chip. */
00336         ssel = 1;
00337 
00338         return 0;
00339     }
00340 
00341     /**
00342      * @brief      Reads and write a buffer from/to the SPI peripheral device at the same time 
00343      *             in 16-bit data mode using synchronous SPI communication.
00344      * @param[out] pBufferToRead pointer to the buffer to read data into.
00345      * @param[in]  pBufferToWrite pointer to the buffer of data to send.
00346      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00347      * @param[in]  NumValues number of 16-bit values to read and write.
00348      * @retval     0 if ok.
00349      * @retval     -1 if data format error.
00350      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00351      *             before calling this function and to enable them again after.
00352      * @note       In order to guarantee this method to work correctly you have to
00353      *             pass buffers which are correctly aligned.
00354      */
00355     int spi_read_write(uint16_t* pBufferToRead, uint16_t* pBufferToWrite, DigitalOut &ssel, uint16_t NumValues)
00356     {
00357     /* Check data format */
00358     if(_bits != 16) return -1;
00359 
00360     /* Select the chip. */
00361         ssel = 0;
00362         
00363         /* Read and write data at the same time. */
00364     for (int i = 0; i < NumValues; i++) {
00365         pBufferToRead[i] = ntohs((uint16_t)write(htons(pBufferToWrite[i])));
00366     }
00367 
00368         /* Unselect the chip. */
00369         ssel = 1;
00370 
00371         return 0;
00372     }
00373 
00374 protected:
00375     inline uint16_t htons(uint16_t x) {
00376 #ifndef __DEV_SPI_BIG_ENDIAN
00377     return (((x)<<8)|((x)>>8));
00378 #else  // __DEV_SPI_BIG_ENDIAN
00379     return (x);
00380 #endif // __DEV_SPI_BIG_ENDIAN
00381     }
00382 
00383     inline uint16_t ntohs(uint16_t x) {
00384     return htons(x);
00385     }
00386 };
00387 
00388 #endif /* __DEV_SPI_H */