11 Replies Latest reply on May 9, 2019 12:36 PM by temac_1467596

    Using Bosch bma2x2 library with SPI

    temac_1467596

      I have a design/project using a CYBLE-224116-01 module connected to BMP280 and BMI005 devices on the SPI bus.  Bosch provides a bma2x2 driver that handles these and a bunch of other ICs on GitHub here https://github.com/BoschSensortec/BMA2x2_driver#fileinfo but I'm struggling on the implementation of the SPI driver calls that the user has to insert in bma2x2_support.c starting around line 422 (in the original file), what I have so far is below which is the tail end of the bma2x2_support.c file but I wondered if anyone has already done this or something similar enough to save me a load of time and hassle the lines I've added are commented with // TMXX - thanks in advance for any help.  I realize I'll have to add toggles to take the respective CS# low but that's not a problem for me.

       

      Ted

       

      /* \Brief: The function is used as SPI bus read

      * \Return : Status of the SPI read

      * \param dev_addr : The device address of the sensor

      * \param reg_addr : Address of the first register,

      *          will data is going to be read

      * \param reg_data : This data read from the sensor,

      *          which is hold in an array

      * \param cnt : The no of bytes of data to be read */

      s8 BMA2x2_SPI_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)

      {

      s32 iError = BMA2x2_INIT_VALUE;

      u8 array[SPI_BUFFER_LEN] = {0xFF};

      u8 stringpos;

      /* For the SPI mode only 7 bits of register addresses are used.

      The MSB of register address is declared the bit what functionality it is

      read/write (read as 1/write as 0)*/

      array[BMA2x2_INIT_VALUE] = reg_addr|BMA2x2_SPI_BUS_READ_CONTROL_BYTE;

      /*read routine is initiated register address is mask with 0x80*/

      /*

      * Please take the below function as your reference for

      * read the data using SPI communication

      * " IERROR = SPI_READ_WRITE_STRING(ARRAY, ARRAY, CNT+1)"

      * add your SPI read function here

      * iError is an return value of SPI read function

      * Please select your valid return value

      * In the driver SUCCESS defined as 0

      * and FAILURE defined as -1

      * Note :

      * This is a full duplex operation,

      * The first read data is discarded, for that extra write operation

      * have to be initiated. For that cnt+1 operation done in the SPI read

      * and write string function

      * For more information please refer data sheet SPI communication:

      */

      // TMXX WHAT DO I PUT HERE? It looks like there would need to be a sequence of commands to send out bytes in the out string, discard the first one back, and then store the rest in the second array but again, no status.

      for (stringpos = BMA2x2_INIT_VALUE; stringpos < cnt; stringpos++) {

      *(reg_data + stringpos) = array[stringpos +

      BMA2x2_BUS_READ_WRITE_ARRAY_INDEX];

      }

      return (s8)iError;

      }

       

       

      /* \Brief: The function is used as SPI bus write

      * \Return : Status of the SPI write

      * \param dev_addr : The device address of the sensor

      * \param reg_addr : Address of the first register,

      *               where data is going to be written

      * \param reg_data : It is a value hold in the array,

      * will be used for write the value into the register

      * \param cnt : The no of byte of data to be write

      */

      s8 BMA2x2_SPI_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)

      {

      s32 iError = BMA2x2_INIT_VALUE;

      u8 array[SPI_BUFFER_LEN * 2];

      u8 stringpos = BMA2x2_INIT_VALUE;

       

       

      for (stringpos = BMA2x2_INIT_VALUE; stringpos < cnt; stringpos++) {

      /* the operation of (reg_addr++)&0x7F done:

      because it ensure the

      0 and 1 of the given value

      It is done only for 8bit operation*/

      array[stringpos * 2] = (reg_addr++) &

      BMA2x2_SPI_BUS_WRITE_CONTROL_BYTE;

      array[stringpos * 2 + BMA2x2_BUS_READ_WRITE_ARRAY_INDEX] =

      *(reg_data + stringpos);

      }

      /* Please take the below function as your reference

      * for writing the data using SPI communication

      * add your SPI write function here.

      * "IERROR = SPI_WRITE_STRING(ARRAY, CNT*2)"

      * iError is a return value of SPI write function

      * Please select your valid return value

      * In the driver SUCCESS defined as 0

           * and FAILURE defined as -1

      */

          SPI_SpiUartPutArray(array, cnt*2); // TM seems to be easy implementation although no status returned

          return 0; // return success

      //return (s8)iError;

      }

       

       

      /* Brief : The delay routine

      * \param : delay in ms

      */

      void BMA2x2_delay_msek(u32 msek)

      {

      CyDelay(msek); // TMXX convert to Cypress mS delay routine

      }

      #endif

        • 1. Re: Using Bosch bma2x2 library with SPI
          GyanC_36

          Hi Ted,

           

              I don't think any code example is already available for these sensors to interface with PSoC over SPI but you can make use of available SPI code examples available for PSoC to get more ideas on APIs.

           

          Please refer below code example for the same -

           

             PSoC-4-BLE/100_Projects_in_100_Days/Day048_SPI_BLE_Bridge at master · cypresssemiconductorco/PSoC-4-BLE · GitHub

           

          -Gyan

          • 2. Re: Using Bosch bma2x2 library with SPI
            temac_1467596

            Gyan,

             

            Thanks, I'll check that out.  I can write my own but didn't want to reinvent the wheel.

             

            Can we leave this thread open for a few days to see if anyone is willing to share code?

             

            Thanks,

             

            Ted

            • 3. Re: Using Bosch bma2x2 library with SPI
              MoTa_728816

              Hi,

               

              Last Nov I posted a sample project for BME680 using I2C,

              and in my toy box of projects, I found one for BME680 using SPI.

               

              As I left my sensor(bme680) in my office and it's the beginning of 10 days national holiday in Japan, I can not test it if it was working or not, but at least the project is compile-able.

               

              Meantime, skimming the code, I was using just a loop to wait for SPI, if you are creating real application, you need to take care of timeout there.

               

              Having written that attached is my bme680 sample using bosch library and adding my SPI functions.

              I hope that at least this can be a hint for you about what kind of APIs to call.

              So please don't get mad at me, when the code is not working ;-)

               

              following functions are in bme680_user.c

              int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)

              int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)

               

              moto

              1 of 1 people found this helpful
              • 4. Re: Using Bosch bma2x2 library with SPI
                temac_1467596

                This is really bugging me.  I can write SPI drivers and understand the technology of clocking data out and getting it in at the same time.  The Bosh bma2x2 driver has 3 SPI functions that the comments SEEM to suggest that I should be adding code to, the one that's most confusing is the BMA2x2_SPI_bus_read function that's in bma2x2_support.c

                 

                /* \Brief: The function is used as SPI bus read
                 * \Return : Status of the SPI read
                 * \param dev_addr : The device address of the sensor
                 * \param reg_addr : Address of the first register,
                 *          will data is going to be read
                 * \param reg_data : This data read from the sensor,
                 *          which is hold in an array
                 * \param cnt : The no of bytes of data to be read */
                s8 BMA2x2_SPI_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
                {
                s32 iError = BMA2x2_INIT_VALUE;
                u8 array[SPI_BUFFER_LEN] = {0xFF};
                u8 stringpos;
                /* For the SPI mode only 7 bits of register addresses are used.
                The MSB of register address is declared the bit what functionality it is
                read/write (read as 1/write as 0)*/
                array[BMA2x2_INIT_VALUE] = reg_addr|BMA2x2_SPI_BUS_READ_CONTROL_BYTE;
                /*read routine is initiated register address is mask with 0x80*/
                /*
                * Please take the below function as your reference for
                * reading data using SPI communication
                * " IERROR = SPI_READ_WRITE_STRING(ARRAY, ARRAY, CNT+1)"
                * add your SPI read function here
                * iError is an return value of SPI read function
                * Please select your valid return value
                * In the driver SUCCESS defined as 0
                * and FAILURE defined as -1
                * Note :
                * This is a full duplex operation,
                * The first read data is discarded, for that extra write operation
                * have to be initiated. For that cnt+1 operation done in the SPI read
                * and write string function
                * For more information please refer data sheet SPI communication:
                */
                
                WHAT TO PUT IN HERE???
                    
                for (stringpos = BMA2x2_INIT_VALUE; stringpos < cnt; stringpos++) {
                *(reg_data + stringpos) = array[stringpos +
                BMA2x2_BUS_READ_WRITE_ARRAY_INDEX];
                }
                return (s8)iError;
                }
                

                 

                I sort of get that, after setting the right CS low, I'd do something like..

                SPI_SpiUartWriteTxData(array[0]);

                and then I could write...

                array[0] = SPI_SpiUartReadRxData();

                 

                Obviously I'd do that with a loop but what's confusing me is that they seem to want me to write out and read in the same array, is that what they really want?

                 

                In this link BMF055-flight-controller/bma2x2_support.c at master · NightHawk32/BMF055-flight-controller · GitHub starting at line 118 they seem to have tackled the same subject but the code provided in the Bosch driver at the end...

                 

                for (stringpos = BMA2x2_INIT_VALUE; stringpos < cnt; stringpos++) {

                *(reg_data + stringpos) = array[stringpos +

                BMA2x2_BUS_READ_WRITE_ARRAY_INDEX];

                }

                return (s8)iError;

                }

                 

                Seems to have been deleted and I don't see where they put the returned bytes into the array?

                 

                HELP!

                • 5. Re: Using Bosch bma2x2 library with SPI
                  temac_1467596

                  Now I'm beginning to wonder whether I'm over complicating this. maybe the Bosch suggestion of...

                   

                  " IERROR = SPI_READ_WRITE_STRING(ARRAY, ARRAY, CNT+1)"

                   

                  Is a typo, I think they meant...

                   

                  " IERROR = SPI_READ_WRITE_STRING(ADDRESS, ARRAY, CNT+1)"

                   

                  That would explain my first concern but still leaves the question of what that last bit of code does?

                  • 6. Re: Using Bosch bma2x2 library with SPI
                    MoTa_728816

                    Dear Ted-san,

                     

                    I think

                       "IERROR = SPI_READ_WRITE_STRING(ARRAY, ARRAY, CNT+1) "

                    is correct, since they filled the first byte

                       array[BMA2x2_INIT_VALUE] = reg_addr | BMA2x2_SPI_BUS_READ_CONTROL_BYTE;

                     

                    BTW, I don't understand why they use BMA2x2_INIT_VALUE for both return value and array index.

                    Meantime, since the array is instantiated at the beginning of this function,

                    having offset for the array does not make sense.

                     

                    So if I interpret BMA2x2_INIT_VALUE as 0, then I can read that they fill the first byte for address to read,

                    then the remaining CNT bytes are for clocking out the result and receiving it to the same array.

                    (I don't like this strategy though).

                     

                    I'd rather write something like

                    iError = SPI_READ_WRITE_STRING(tx_buffer, rx_buffer, CNT+1) ;

                    so that debugging will be easier.

                     

                    Anyway I think that the intention of s8 BMA2x2_SPI_bus_read() is

                    (1) Sending read request for the reg_addr

                    (2) Receiving cnt bytes to reg_data[]

                    And if any of PSoC SPI API returns error/failure, set iError to non zero value.

                     

                    Best Regards,

                    28-Apr-2019

                    Motoo Tanaka

                    1 of 1 people found this helpful
                    • 7. Re: Using Bosch bma2x2 library with SPI
                      temac_1467596

                      Moto-san,

                       

                      Thanks so much for your help, I work on my own and it's difficult to get my mind straight when I read code that seems not to be doing something logical.

                       

                      I've decided to try to adapt the code in this link BMF055-flight-controller/bma2x2_support.c at master · NightHawk32/BMF055-flight-controller · GitHub into my project and convert the Atmel? SPI calls to something equivalent in PSoC GCC.  I'll let you know how I get on but I'm having cataract eye surgery tomorrow so I may not be around for a few days.

                       

                      Thanks for helping during your holiday, hope you're having a nice rest.

                       

                      Ted Mawson

                      • 8. Re: Using Bosch bma2x2 library with SPI
                        temac_1467596

                        All my SPI calls e.g.

                         

                        SPI_SpiUartWriteTxData(dataToSend);

                         

                        Don't return a stats value to say if the SPI action was successful.  The bma2x2 code assumes that there's some kind of iError parameter that is set to 0 if all is good.  Is there a way to read a status register or flag to find out if the last SPI transaction was dowe without error?

                        • 9. Re: Using Bosch bma2x2 library with SPI
                          temac_1467596

                          I haven't tried it yet as I need to write a test function to see values streaming but here is the updated bma2x2_support.c file

                          /**
                          *
                          *
                          **************************************************************************
                          * Copyright (C) 2015 Bosch Sensortec GmbH. All Rights Reserved.
                          *
                          * File: bma2x2_support.c
                          *
                          * Date: 2015/02/02
                          *
                          * Revision: 1.0
                          *
                          * Usage: Part of BMF055 Data Stream Project
                          *
                          **************************************************************************
                          * \section License
                          *
                          * Redistribution and use in source and binary forms, with or without
                          * modification, are permitted provided that the following conditions are met:
                          *
                          *   Redistributions of source code must retain the above copyright
                          *   notice, this list of conditions and the following disclaimer.
                          *
                          *   Redistributions in binary form must reproduce the above copyright
                          *   notice, this list of conditions and the following disclaimer in the
                          *   documentation and/or other materials provided with the distribution.
                          *
                          *   Neither the name of the copyright holder nor the names of the
                          *   contributors may be used to endorse or promote products derived from
                          *   this software without specific prior written permission.
                          *
                          * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
                          * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
                          * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                          * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                          * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
                          * OR CONTRIBUTORS BE LIABLE FOR ANY
                          * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
                          * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
                          * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                          * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                          * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                          * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                          * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                          * ANY WAY OUT OF THE USE OF THIS
                          * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
                          *
                          * The information provided is believed to be accurate and reliable.
                          * The copyright holder assumes no responsibility
                          * for the consequences of use
                          * of such information nor for any infringement of patents or
                          * other rights of third parties which may result from its use.
                          * No license is granted by implication or otherwise under any patent or
                          * patent rights of the copyright holder.
                          *
                          *
                          *************************************************************************/
                          /*!
                          *
                          * @file bma2x2_support.c
                          * @author Bosch Sensortec
                          *
                          * @brief Functions declared in bma2x2_support.h file are defined here.
                          *
                          *
                          */
                          
                          
                          
                          
                          /************************************************************************/
                          /* Include Own Header                                                   */
                          /************************************************************************/
                          #include <project.h>
                          #include <bma2x2_support.h>
                          
                          
                          /************************************************************************/
                          /* Function Definitions                                                 */
                          /************************************************************************/
                          
                          
                          /*!
                          * @brief Initializes BMA280 accelerometer sensor and its required connections
                          *
                          * @param [in] NULL
                          *
                          * @param [out] NULL
                          *
                          * @return NULL
                          *
                          */
                          void bma_init(void)
                          {
                          /* Configure an SPI slave instance for the sensor */
                            //spi_configure_slave(&bma2x2_spi_slave, BMA2x2_SS_PIN); TMXXX
                          
                              /* Assign functions required by sensor API */
                          bma2x2.bus_write = &bma_spi_write;
                          bma2x2.bus_read = &bma_spi_read;
                          bma2x2.delay_msec = &bma_delay_msec;
                          
                          /* Call sensor API initialization function */
                          bma2x2_init(&bma2x2);
                          }
                          
                          
                          /*!
                          * @brief Sends data to BMA280 via SPI
                          *
                          * @param[in] dev_addr Device I2C slave address (not used)
                          *
                          * @param[in] reg_addr Address of destination register
                          *
                          * @param[in] reg_data Pointer to data buffer to be sent
                          *
                          * @param[in] length Length of the data to be sent
                          *
                          * @retval 0 BMA2x2_SUCCESS
                          * @retval -1 BMA2x2_ERROR
                          *
                          */
                          int8_t bma_spi_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t length)
                          {
                            // enum status_code bma_write_stat = STATUS_NO_CHANGE; //TMXX4
                          
                              (void) dev_addr ;
                              uint16_t i ;
                              SPI_SpiUartClearTxBuffer();
                              SPI_SpiUartClearRxBuffer();
                              
                          ACC_CS_Write(0);
                              CyDelayUs(10) ;
                              
                              do {
                                  SPI_SpiUartWriteTxData(reg_addr);
                              } while(SPI_SpiUartGetTxBufferSize());
                              
                              for (i = 0 ; i < length ; i++ ) {
                                  do {
                                      SPI_SpiUartWriteTxData(reg_data[i]) ;
                                  } while(SPI_SpiUartGetTxBufferSize());
                              }
                              while(!SPI_SpiIsBusBusy()) {
                                  ;   // TMXX4 wait for SPI to complete
                              }
                              SPI_SpiUartClearRxBuffer(); // TMXX4 throw away junk received bytes
                              
                          ACC_CS_Write(1);
                          
                          return 0;       // TMXX4 for now, just return sucess
                          }
                          
                          
                          /*!
                          * @brief Receives data from BMA280 on SPI
                          *
                          * @param[in] dev_addr Device I2C slave address (not used)
                          *
                          * @param[in] reg_addr Address of destination register
                          *
                          * @param[out] reg_data Pointer to data buffer to be received
                          *
                          * @param[in] length Length of the data to be received
                          *
                          * @retval 0 BMA2x2_SUCCESS
                          * @retval -1 BMA2x2_ERROR
                          *
                          */
                          int8_t bma_spi_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *rx_data, uint8_t length)
                          {
                          // enum status_code bma_read_stat = STATUS_NO_CHANGE;
                              (void) dev_addr ;
                              uint16_t i ;    
                              SPI_SpiUartClearTxBuffer();
                              SPI_SpiUartClearRxBuffer();
                              
                              ACC_CS_Write(0);
                              CyDelayUs(10) ;
                              
                              SPI_SpiUartWriteTxData(0x80 | reg_addr) ;
                              while(SPI_SpiUartGetRxBufferSize() < 1) {
                                  ;
                              }
                              rx_data[0] = SPI_SpiUartReadRxData() ;      // read dummy byte
                              for (i = 0 ; i < length ; i++ ) {
                                  SPI_SpiUartWriteTxData(0x80 | (reg_addr+i)) ;
                                  while(SPI_SpiUartGetTxBufferSize()) {
                                      ;
                                  }
                                  while(SPI_SpiUartGetRxBufferSize() < 1) {
                                      ;
                                  }
                                  rx_data[i] = SPI_SpiUartReadRxData() ;
                              }
                              ACC_CS_Write(1) ;
                          return 0;
                          }
                          
                          
                          /*!
                          * @brief Initiates a delay of the length of the argument in milliseconds
                          *
                          * @param[in] msec Delay length in terms of milliseconds
                          *
                          * @param[out] NULL
                          *
                          * @return NULL
                          *
                          */
                          void bma_delay_msec(uint32_t msec)
                          {
                          CyDelay(msec);
                          }
                          
                          • 10. Re: Using Bosch bma2x2 library with SPI
                            MoTa_728816

                            Dear Ted-san,

                             

                            (Warning) As I'm very good at making mistakes, please take following with a grain of salt.

                             

                            Your bmi_spi_read() seems to be OK to me,

                            except there is no timeout checking,

                            but bmi_spi_write() seems to be somewhat odd to me.

                             

                            your code

                            > do {

                            >     SPI_SpiUartWriteTxData(reg_addr) ;

                            >  } while(SPI_SpiUartGetTxBufferSize()) ;

                            >

                            > for (i = 0 ; i < length ; i++) {

                            >     do {

                            >          SPI_SpiUartWriteTxDat(reg_data[i]) ;

                            >     } while(SPI_SpiUartGetTxBufferSize()) ;

                            > }

                            >

                             

                            I would write

                            < // sending address

                            < SPI_SpiUartWriteTxData(reg_addr) ;

                            < while(SPI_SpiUartGetTxBufferSize()) {

                            <    // need to check time out here

                            <  }

                            <

                            > // sending data (pattern1)

                            > for (i = 0 ; i < length ; i++ ) {

                            > SPI_SpiUartWriteTxData(reg_data[i]) ;

                            >     while(SPI_SpiUartGetTxBufferSize()) {

                            >        // need to check time out here

                            >     }

                            > }

                            or the later half could be

                            > // sending data (patter2)

                            > SPI_SpiUartPutArray(reg_data, length) ;

                            > while(SPI_SpiUartGetTxBufferSize()) {

                            >    // need to check time out here

                            >}

                             

                            In an usual sample, light weight application using "while() ; " would be OK,

                            but for some critical applications, such as automotive, medical, aero,

                            dead lock can be fatal.

                            So usually some time out checking is due where I wrote "// need to check time out here".

                             

                            There should be many strategies doing it, but for a simple example,

                             

                            #define SPI_TIME_OUT_MS 500  // you decide the number for your application

                            ...

                            int timeout_count ;

                            SPI_SpiUartWriteTxData(reg_data[i]) ;

                            timeout_count = 0 ;

                            while(SPI_SpiUartGetTxBufferSize()) {

                                 timeout_count++ ;

                                 if (timeout_count >= SPI_TIME_OUT_MS) {

                                      // this is the place where we set return value to non-zero

                                      return( 1 ) ; // any non-zero number, you assigned for SPI timeout

                                 }

                                CyDelay(1) ; // wait 1ms

                            }

                             

                            Best Regards,

                            29-Apr-2019

                            Motoo Tanaka

                            • 11. Re: Using Bosch bma2x2 library with SPI
                              temac_1467596

                              OK, I finally got round to working on this and have been successful, mostly thanks to Motoo Tanaka.

                               

                              The code I ended up with for the SPI read and write functions is below; there's a weird part of the read where it appears that the dummy data from the sending of the reg_addr is included in index 0 of the returned array; the ADC values that come back from the accelerometer all look fine though.  I'm not quite clear how to set the parameters in the bma2x2 structure variable but I'll experiment.

                               

                              Thanks to all who contributed.

                               

                              Ted M

                              /************************************************************************/
                              /* Function Definitions                                                 */
                              /************************************************************************/
                              
                              
                              /*!
                              * @brief Initializes BMA280 accelerometer sensor and its required connections
                              *
                              * @param [in] NULL
                              *
                              * @param [out] NULL
                              *
                              * @return NULL
                              *
                              */
                              void bma_init(void)
                              {
                              /* Configure an SPI slave instance for the sensor */
                                //spi_configure_slave(&bma2x2_spi_slave, BMA2x2_SS_PIN); TMXXX
                              
                                  /* Assign functions required by sensor API */
                              bma2x2.bus_write = &bma_spi_write;
                              bma2x2.bus_read = &bma_spi_read;
                              bma2x2.delay_msec = &bma_delay_msec;
                              
                              /* Call sensor API initialization function */
                              bma2x2_init(&bma2x2);
                              }
                              
                              
                              /*!
                              * @brief Sends data to BMA280 via SPI
                              *
                              * @param[in] dev_addr Device I2C slave address (not used)
                              *
                              * @param[in] reg_addr Address of destination register
                              *
                              * @param[in] reg_data Pointer to data buffer to be sent
                              *
                              * @param[in] length Length of the data to be sent
                              *
                              * @retval 0 BMA2x2_SUCCESS
                              * @retval -1 BMA2x2_ERROR
                              *
                              */
                              int8_t bma_spi_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t length)
                              {
                                // enum status_code bma_write_stat = STATUS_NO_CHANGE; //TMXX4
                              
                                  (void) dev_addr ;
                                  uint16_t i ;
                                  int timeout_count;
                                  
                              ACC_CS_Write(0);
                                  CyDelayUs(10) ;
                              
                              
                                  SPI_SpiUartClearTxBuffer();
                                  SPI_SpiUartClearRxBuffer();
                                  
                                  SPI_SpiUartWriteTxData(reg_addr);       // send out the register address
                                  timeout_count = 0;
                                  while(SPI_SpiUartGetTxBufferSize()) {   // wait until TX buffer is empty
                                      timeout_count++;
                                      if (timeout_count >= SPI_TIME_OUT_MS) {
                                          return (1);   // any non-zero number, you assigned for SPI timeout
                                      }
                                  }
                                  
                                  SPI_SpiUartClearTxBuffer();             // this is a write function so...
                                  SPI_SpiUartClearRxBuffer();             // discard any RXd data
                                  
                                  for (i = 0 ; i < length ; i++ ) {
                                      SPI_SpiUartWriteTxData(reg_data[i]) ;
                                      while(SPI_SpiUartGetTxBufferSize()) {   // wait until TX buffer is empty
                                          timeout_count++;
                                          if (timeout_count >= SPI_TIME_OUT_MS) {
                                              return (1);                 // any non-zero number, you assigned for SPI timeout
                                          }
                                      }
                                  }
                                  SPI_SpiUartClearTxBuffer();             // this is a write function so...
                                  SPI_SpiUartClearRxBuffer();             // discard any RXd data
                                  
                              ACC_CS_Write(1);
                              
                              return (0);       // TMXX4 return sucess
                              }
                              
                              
                              /*!
                              * @brief Receives data from BMA280 on SPI
                              *
                              * @param[in] dev_addr Device I2C slave address (not used)
                              *
                              * @param[in] reg_addr Address of destination register
                              *
                              * @param[out] reg_data Pointer to data buffer to be received
                              *
                              * @param[in] length Length of the data to be received
                              *
                              * @retval 0 BMA2x2_SUCCESS
                              * @retval -1 BMA2x2_ERROR
                              *
                              */
                              int8_t bma_spi_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *rx_data, uint8_t length)
                              {
                              // enum status_code bma_read_stat = STATUS_NO_CHANGE;
                                  (void) dev_addr ;
                                  uint16_t i ;
                                  int timeout_count;
                                  
                                  ACC_CS_Write(0);
                                  CyDelayUs(10) ;
                                  
                                  SPI_SpiUartClearTxBuffer();
                                  SPI_SpiUartClearRxBuffer();    
                                  
                                  SPI_SpiUartWriteTxData(0x80 | reg_addr) ;
                                  timeout_count = 0;
                                  while(SPI_SpiUartGetRxBufferSize() < 1) {
                                      timeout_count++;
                                      if (timeout_count >= SPI_TIME_OUT_MS) {
                                          return (1);   // any non-zero number, you assigned for SPI timeout
                                      }
                                  }
                                  rx_data[0] = SPI_SpiUartReadRxData() ;      // read dummy byte (we'll overwrite in a moment)
                                  for (i = 0 ; i < length ; i++ ) {
                                      SPI_SpiUartWriteTxData(0x80 | (reg_addr+i));   // suspicious that the dummy byte is stil there in xxx[0]
                                      timeout_count = 0;
                                      while(SPI_SpiUartGetTxBufferSize()) {
                                          timeout_count++;
                                          if (timeout_count >= SPI_TIME_OUT_MS) {
                                              return (1);   // any non-zero number, you assigned for SPI timeout
                                          }
                                      }
                                      timeout_count = 0;
                                      while(SPI_SpiUartGetRxBufferSize() < 1) {
                                          timeout_count++;
                                          if (timeout_count >= SPI_TIME_OUT_MS) {
                                              return (1);   // any non-zero number, you assigned for SPI timeout
                                          }
                                      }
                                      rx_data[i] = SPI_SpiUartReadRxData() ;
                                  }
                                  ACC_CS_Write(1) ;
                              return 0;
                              }
                              
                              
                              /*!
                              * @brief Initiates a delay of the length of the argument in milliseconds
                              *
                              * @param[in] msec Delay length in terms of milliseconds
                              *
                              * @param[out] NULL
                              *
                              * @return NULL
                              *
                              */
                              void bma_delay_msec(uint32_t msec)
                              {
                              CyDelay(msec);
                              }