Fork of X_NUCLEO_COMMON lib adding 16-bit SPI support

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
00005  * @version V1.0.1
00006  * @date    February 11th, 2016
00007  * @brief   Header file for a special SPI class DevSPI which provides some
00008  *          helper function for on-board communication.
00009  ******************************************************************************
00010  * @attention
00011  *
00012  * <h2><center>&copy; COPYRIGHT(c) 2014 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 /* Classes -------------------------------------------------------------------*/
00047 /** Helper class DevSPI providing functions for SPI communication common for a
00048  *  series of SPI devices.
00049  */
00050 class DevSPI : public SPI
00051 {
00052  public:
00053     /*
00054      * Create a DevSPI interface.
00055      * @param mosi pin name of the MOSI pin of the SPI device to be used for communication.
00056      * @param miso pin name of the MISO pin of the SPI device to be used for communication.
00057      * @param sclk pin name of the SCLK pin of the SPI device to be used for communication.
00058      */
00059     DevSPI(PinName mosi, PinName miso, PinName sclk) : SPI(mosi, miso, sclk)
00060     {
00061         /* Set default configuration. */
00062         setup(8, 3, 1E6);
00063     }
00064 
00065     /*
00066      * Setup the spi.
00067      * Typically:
00068      *  + 8 bit data;
00069      *  + high steady state clock;
00070      *  + second edge capture;
00071      *  + 1MHz clock rate.
00072      *
00073      * @param bits         Number of bits per SPI frame (4 - 16)
00074      * @param mode         Clock polarity and phase mode (0 - 3)
00075      * @param frequency_hz SCLK frequency in hz (default = 1MHz)
00076      *
00077      * @code
00078      * mode | POL PHA
00079      * -----+--------
00080      *   0  |  0   0
00081      *   1  |  0   1
00082      *   2  |  1   0
00083      *   3  |  1   1
00084      * @endcode
00085      */
00086     void setup(int bits, int mode = 0, int frequency_hz = 1E6)
00087     {
00088         /* Set given configuration. */
00089         format(bits, mode);
00090         frequency(frequency_hz);
00091     }
00092 
00093     /**
00094      * @brief      Writes a buffer to the SPI peripheral device.
00095      * @param[in]  pBuffer pointer to the buffer of data to send.
00096      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00097      * @param[in]  NumBytesToWrite number of bytes to write.
00098      * @retval     0 if ok.
00099      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00100      *             before calling this function and to enable them again after.
00101      */
00102     int spi_write(uint8_t* pBuffer, DigitalOut ssel, uint16_t NumBytesToWrite)
00103     {
00104         /* Select the chip. */
00105         ssel = 0;
00106         
00107         /* Write data. */
00108         if (_bits == 16) {
00109             uint16_t dataToWrite;
00110             for (int i = 0; i < NumBytesToWrite; i += 2) {
00111                 dataToWrite = convertFrom8To16(pBuffer);
00112                 write(dataToWrite);
00113                 pBuffer += sizeof(uint16_t);
00114             }
00115 
00116         } else if(_bits == 8) {
00117             for (int i = 0; i < NumBytesToWrite; i++) {
00118                 write(pBuffer[i]);
00119             }
00120         }
00121 
00122         /* Unselect the chip. */
00123         ssel = 1;
00124 
00125         return 0;
00126     }
00127 
00128     /**
00129      * @brief      Reads a buffer from the SPI peripheral device.
00130      * @param[out] pBuffer pointer to the buffer to read data into.
00131      * @param[in]  ssel GPIO of the SSEL pin of the SPI device to be used for communication.
00132      * @param[in]  NumBytesToRead number of bytes to read.
00133      * @retval     0 if ok.
00134      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00135      *             before calling this function and to enable them again after.
00136      */
00137     int spi_read(uint8_t* pBuffer, DigitalOut ssel, uint16_t NumBytesToRead)
00138     {
00139         /* Select the chip. */
00140         ssel = 0;
00141         
00142         /* Read data. */
00143         if (_bits == 16) {
00144             uint16_t dataToRead;
00145             for (int i = 0; i < NumBytesToRead; i += 2) {
00146                 dataToRead = write(0x00);
00147                 convertFrom16To8(dataToRead, pBuffer);
00148                 pBuffer += sizeof(uint16_t);
00149             }
00150 
00151         } else if(_bits == 8) {
00152             for (int i = 0; i < NumBytesToRead; i++) {
00153                 pBuffer[i] = write(0x00);
00154             }
00155         }
00156 
00157         /* Unselect the chip. */
00158         ssel = 1;
00159 
00160         return 0;
00161     }
00162 
00163     /**
00164      * @brief      Reads and write a buffer from/to the SPI peripheral device at the same time.
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      * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
00171      *             before calling this function and to enable them again after.
00172      */
00173     int spi_read_write(uint8_t* pBufferToRead, uint8_t* pBufferToWrite, DigitalOut ssel, uint16_t NumBytes)
00174     {
00175         /* Select the chip. */
00176         ssel = 0;
00177         
00178         /* Read and write data at the same time. */
00179         if (_bits == 16) {
00180             uint16_t dataToRead;
00181             uint16_t dataToWrite;
00182 
00183             for (int i = 0; i < NumBytes; i += 2) {
00184                 dataToWrite = convertFrom8To16(pBufferToWrite);
00185                 
00186                 dataToRead = write(dataToWrite);
00187                 
00188                 convertFrom16To8(dataToRead, pBufferToRead);
00189                 
00190                 pBufferToWrite += sizeof(uint16_t);
00191                 pBufferToRead += sizeof(uint16_t);
00192             }
00193 
00194         } else if(_bits == 8) {
00195             for (int i = 0; i < NumBytes; i++) {
00196                 pBufferToRead[i] = write(pBufferToWrite[i]);
00197             }
00198         }
00199 
00200         /* Unselect the chip. */
00201         ssel = 1;
00202 
00203         return 0;
00204     }
00205 
00206 private:
00207 
00208     /**
00209      * @brief      Converts two uint8_t words into one of uint16_t
00210      * @param[in]  ptr pointer to the buffer of data to be converted.
00211      * @retval     16-bit data.
00212      */
00213     uint16_t convertFrom8To16(uint8_t *ptr)
00214     {
00215         uint16_t data16 = 0x0000;
00216         
00217         data16 = *ptr;
00218         data16 |= *(++ptr) << 8;
00219         
00220         return data16;
00221     }
00222 
00223     /**
00224      * @brief      Converts one uint16_t word into two uint8_t
00225      * @param[in]  ptr pointer to the buffer of uint8_t words.
00226      * @param[in]  16-bit data.
00227      * @retval     none.
00228      */
00229     void convertFrom16To8(uint16_t data16, uint8_t *ptr)
00230     {
00231         *(ptr) = data16 & 0x00FF;
00232         *(++ptr) = (data16 >> 8) & 0x00FF;
00233     }
00234 
00235 };
00236 
00237 #endif /* __DEV_SPI_H */