Sean Wilson / Mbed OS AdiSense1000_V21

Fork of AdiSense1000 by PoC_Team

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers adi_sense_spi.cpp Source File

adi_sense_spi.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 Copyright 2017 (c) Analog Devices, Inc.
00003 
00004 All rights reserved.
00005 
00006 Redistribution and use in source and binary forms, with or without
00007 modification, are permitted provided that the following conditions are met:
00008   - Redistributions of source code must retain the above copyright
00009     notice, this list of conditions and the following disclaimer.
00010   - Redistributions in binary form must reproduce the above copyright
00011     notice, this list of conditions and the following disclaimer in
00012     the documentation and/or other materials provided with the
00013     distribution.
00014   - Neither the name of Analog Devices, Inc. nor the names of its
00015     contributors may be used to endorse or promote products derived
00016     from this software without specific prior written permission.
00017   - The use of this software may or may not infringe the patent rights
00018     of one or more patent holders. This license does not release you
00019     from the requirement that you obtain separate licenses from these
00020     patent holders to use this software.
00021   - Use of the software either in source or binary form, must be run
00022     on or directly connected to an Analog Devices Inc. component.
00023 
00024 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
00025 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
00026 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00027 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
00028 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
00030 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00032 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *****************************************************************************/
00036 
00037 /*!
00038  ******************************************************************************
00039  * @file:
00040  * @brief:  ADISENSE OS-dependent wrapper layer for SPI interface
00041  *-----------------------------------------------------------------------------
00042  */
00043 
00044 #include <mbed.h>
00045 
00046 #include "inc/adi_sense_spi.h"
00047 #include "inc/adi_sense_log.h"
00048 
00049 #define ADI_SENSE_SPI_MODE       0 /* CPOL=0, CPHA=0 */
00050 #define ADI_SENSE_SPI_FRAME_SIZE 8 /* 8-bit frame size */
00051 
00052 class SpiContext
00053 {
00054 public:
00055     SpiContext(
00056         PinName mosiPin,
00057         PinName misoPin,
00058         PinName sckPin,
00059         PinName csPin,
00060         unsigned maxSpeed);
00061 
00062     int transfer(
00063         void *pTxData,
00064         void *pRxData,
00065         unsigned nLength,
00066         bool bCsHold);
00067 
00068 private:
00069     SPI _spi;
00070     DigitalOut _cs;
00071 
00072     event_callback_t _callback;
00073     volatile int     _cbEvent;
00074     volatile bool    _cbFired;
00075 
00076     void _cbHandler(
00077         int event);
00078 
00079     int _waitForCallback(
00080         void);
00081 };
00082 
00083 SpiContext::SpiContext(PinName mosiPin,
00084                        PinName misoPin,
00085                        PinName sckPin,
00086                        PinName csPin,
00087                        unsigned maxSpeed)
00088     : _spi(mosiPin, misoPin, sckPin),
00089       _cs(csPin, 1)
00090 {
00091     _cbEvent = 0;
00092     _cbFired = false;
00093     _callback = callback(this, &SpiContext::_cbHandler);
00094 
00095     _spi.format(ADI_SENSE_SPI_FRAME_SIZE, ADI_SENSE_SPI_MODE);
00096     _spi.frequency(maxSpeed);
00097 }
00098 
00099 void SpiContext::_cbHandler(int event)
00100 {
00101     _cbEvent = event;
00102     _cbFired = true;
00103 }
00104 
00105 int SpiContext::_waitForCallback(void)
00106 {
00107     int rc = 0;
00108 
00109     while ((_cbFired != true) && (_cbEvent != SPI_EVENT_COMPLETE))
00110     { ; }
00111 
00112     _cbFired = false;
00113     _cbEvent = 0;
00114 
00115     return rc;
00116 }
00117 
00118 int SpiContext::transfer(
00119     void *pTxData,
00120     void *pRxData,
00121     unsigned nLength,
00122     bool bCsHold)
00123 {
00124     int rc = 0;
00125 
00126     _cs = 0;
00127 
00128     rc  = _spi.transfer((uint8_t *)pTxData, nLength,
00129                         (uint8_t *)pRxData, nLength,
00130                         _callback, SPI_EVENT_COMPLETE);
00131     if (rc < 0)
00132     {
00133         _cs = 1;
00134         return rc;
00135     }
00136 
00137     rc = _waitForCallback();
00138     if ((rc < 0) || !bCsHold)
00139         _cs = 1;
00140 
00141     return rc;
00142 }
00143 
00144 #ifdef __cplusplus
00145 extern "C" {
00146 #endif
00147 
00148 /*
00149  * Open the SPI interface and allocate resources
00150  */
00151 ADI_SENSE_RESULT  adi_sense_SpiOpen(
00152     ADI_SENSE_PLATFORM_SPI_CONFIG *pConfig,
00153     ADI_SENSE_SPI_HANDLE  *phDevice)
00154 {
00155     SpiContext *pCtx = new SpiContext((PinName)pConfig->mosiPin,
00156                                       (PinName)pConfig->misoPin,
00157                                       (PinName)pConfig->sckPin,
00158                                       (PinName)pConfig->csPin,
00159                                       pConfig->maxSpeedHz);
00160     if (!pCtx)
00161     {
00162         ADI_SENSE_LOG_ERROR("Failed to allocate memory for SPI interface");
00163         return ADI_SENSE_NO_MEM ;
00164     }
00165 
00166     *phDevice = reinterpret_cast<ADI_SENSE_SPI_HANDLE >(pCtx);
00167     return ADI_SENSE_SUCCESS ;
00168 }
00169 
00170 /*
00171  * Execute a bi-directional data transfer on the SPI interface
00172  */
00173 ADI_SENSE_RESULT 
00174 adi_sense_SpiTransfer(
00175     ADI_SENSE_SPI_HANDLE  hDevice,
00176     void *pTxData,
00177     void *pRxData,
00178     unsigned nLength,
00179     bool bCsHold)
00180 {
00181     SpiContext *pCtx = reinterpret_cast<SpiContext *>(hDevice);
00182 
00183     if (pCtx->transfer(pTxData, pRxData, nLength, bCsHold) < 0)
00184     {
00185         ADI_SENSE_LOG_ERROR("Failed to complete SPI transfer");
00186         return ADI_SENSE_FAILURE ;
00187     }
00188 
00189     return ADI_SENSE_SUCCESS ;
00190 }
00191 
00192 /*
00193  * Close the SPI interface and free resources
00194  */
00195 void adi_sense_SpiClose(
00196     ADI_SENSE_SPI_HANDLE  hDevice)
00197 {
00198     SpiContext *pCtx = reinterpret_cast<SpiContext *>(hDevice);
00199 
00200     delete pCtx;
00201 }
00202 
00203 #ifdef __cplusplus
00204 }
00205 #endif
00206 
00207 /*!
00208  * @}
00209  */