project

Fork of X_NUCLEO_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BlueNRGDevice.cpp Source File

BlueNRGDevice.cpp

Go to the documentation of this file.
00001 /* mbed Microcontroller Library
00002 * Copyright (c) 2006-2013 ARM Limited
00003 *
00004 * Licensed under the Apache License, Version 2.0 (the "License");
00005 * you may not use this file except in compliance with the License.
00006 * You may obtain a copy of the License at
00007 *
00008 *     http://www.apache.org/licenses/LICENSE-2.0
00009 *
00010 * Unless required by applicable law or agreed to in writing, software
00011 * distributed under the License is distributed on an "AS IS" BASIS,
00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 * See the License for the specific language governing permissions and
00014 * limitations under the License.
00015 */
00016 
00017 /**
00018   ******************************************************************************
00019   * @file    BlueNRGDevice.cpp 
00020   * @author  STMicroelectronics
00021   * @brief   Implementation of BLEDeviceInstanceBase
00022   ******************************************************************************
00023   * @copy
00024   *
00025   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00026   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00027   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
00028   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00029   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00030   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00031   *
00032   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
00033   */ 
00034   
00035 /** @defgroup BlueNRGDevice
00036  *  @brief BlueNRG BLE_API Device Adaptation
00037  *  @{
00038  */
00039  
00040 #include "mbed.h"
00041 #include "BlueNRGDevice.h"
00042 #include "BlueNRGGap.h"
00043 #include "BlueNRGGattServer.h"
00044 
00045 #include "btle.h"
00046 #include "Utils.h"
00047 #include "osal.h"
00048 
00049 #include "debug.h"
00050 #include "stm32_bluenrg_ble.h "
00051 
00052 extern "C" {
00053     #include "hci.h"
00054 }
00055 
00056 #define HEADER_SIZE 5
00057 #define MAX_BUFFER_SIZE 255
00058 
00059 /**
00060  * The singleton which represents the BlueNRG transport for the BLEDevice.
00061  *
00062  * See file 'x_nucleo_idb0xa1_targets.h' for details regarding the peripheral pins used!
00063  */
00064 #include "x_nucleo_idb0xa1_targets.h"
00065 
00066 BlueNRGDevice bluenrgDeviceInstance(IDB0XA1_PIN_SPI_MOSI,
00067                                     IDB0XA1_PIN_SPI_MISO,
00068                                     IDB0XA1_PIN_SPI_SCK,
00069                                     IDB0XA1_PIN_SPI_nCS,
00070                                     IDB0XA1_PIN_SPI_RESET,
00071                                     IDB0XA1_PIN_SPI_IRQ);
00072 
00073 /**
00074 * BLE-API requires an implementation of the following function in order to
00075 * obtain its transport handle.
00076 */
00077 BLEInstanceBase *
00078 createBLEInstance(void)
00079 {
00080     return (&bluenrgDeviceInstance);
00081 }
00082 
00083 /**************************************************************************/
00084 /**
00085     @brief  Constructor
00086      * @param mosi mbed pin to use for MOSI line of SPI interface
00087      * @param miso mbed pin to use for MISO line of SPI interface
00088      * @param sck mbed pin to use for SCK line of SPI interface
00089      * @param cs mbed pin to use for not chip select line of SPI interface
00090      * @param rst mbed pin to use for BlueNRG reset
00091      * @param irq mbed pin for BlueNRG IRQ
00092 */
00093 /**************************************************************************/
00094 BlueNRGDevice::BlueNRGDevice(PinName mosi,
00095                              PinName miso,
00096                              PinName sck,
00097                              PinName cs,
00098                              PinName rst,
00099                              PinName irq) : 
00100     isInitialized(false), spi_(mosi, miso, sck), nCS_(cs), rst_(rst), irq_(irq)
00101 {
00102     // Setup the spi for 8 bit data, low clock polarity,
00103     // 1-edge phase, with an 8MHz clock rate
00104     spi_.format(8, 0);
00105     spi_.frequency(8000000);
00106     
00107     // Deselect the BlueNRG chip by keeping its nCS signal high
00108     nCS_ = 1;
00109 
00110     wait_us(500);
00111 }
00112 
00113 /**************************************************************************/
00114 /**
00115     @brief  Destructor
00116 */
00117 /**************************************************************************/
00118 BlueNRGDevice::~BlueNRGDevice(void)
00119 {
00120 }
00121 
00122 
00123 /**
00124     @brief  Initialises anything required to start using BLE
00125     @param[in] void
00126     @returns    ble_error_t
00127 */
00128 ble_error_t BlueNRGDevice::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback)
00129 {
00130     if (isInitialized) {
00131             BLE::InitializationCompleteCallbackContext context = {
00132                 BLE::Instance(instanceID),
00133                 BLE_ERROR_ALREADY_INITIALIZED
00134             };
00135             callback.call(&context);
00136             return BLE_ERROR_ALREADY_INITIALIZED;
00137         }
00138 
00139     // Set the interrupt handler for the device
00140     irq_.mode(PullDown); // betzw: set irq mode
00141     irq_.rise(&HCI_Isr);
00142     
00143     /* ToDo: Clear memory contents, reset the SD, etc. */
00144     // By default, we set the device GAP role to PERIPHERAL
00145     btle_init(BlueNRGGap::getInstance().getIsSetAddress(), GAP_PERIPHERAL_ROLE_IDB04A1);
00146     
00147     isInitialized = true;
00148     BLE::InitializationCompleteCallbackContext context = {
00149             BLE::Instance(instanceID),
00150             BLE_ERROR_NONE
00151     };
00152     callback.call(&context);
00153     
00154     return BLE_ERROR_NONE;
00155 }
00156 
00157 
00158 /**
00159     @brief  Resets the BLE HW, removing any existing services and
00160             characteristics
00161     @param[in] void
00162     @returns    ble_error_t
00163 */
00164 ble_error_t BlueNRGDevice::reset(void)
00165 {
00166     wait_us(500);
00167 
00168     /* Reset BlueNRG SPI interface */
00169       rst_ = 0;
00170     wait_us(5);
00171       rst_ = 1;
00172     wait_us(5);
00173 
00174     /* Wait for the radio to come back up */
00175     wait_us(500);
00176     
00177     isInitialized = false;
00178 
00179     return BLE_ERROR_NONE;
00180 }
00181 
00182 /*!
00183   @brief  Wait for any BLE Event like BLE Connection, Read Request etc.    
00184   @param[in] void
00185   @returns    char *      
00186 */
00187 void BlueNRGDevice::waitForEvent(void)
00188 {
00189     bool must_return = false;
00190 
00191     do {
00192         BlueNRGGap::getInstance().Process();
00193         
00194         HCI_Process();
00195         
00196         if(must_return) return;
00197 
00198         __WFE(); /* it is recommended that SEVONPEND in the
00199                 System Control Register is NOT set */
00200         must_return = true; /* after returning from WFE we must guarantee
00201                        that conrol is given back to main loop before next WFE */
00202     } while(true);
00203 
00204 } 
00205  
00206 /*!
00207     @brief  get GAP version
00208     @param[in] void
00209     @returns    char *
00210 */
00211 const char *BlueNRGDevice::getVersion(void)
00212 {
00213     char *version = new char[6];
00214     memcpy((void *)version, "1.0.0", 5);
00215     return version;
00216 }
00217 
00218 /**************************************************************************/
00219 /*!
00220     @brief  get reference to GAP object
00221     @param[in] void
00222     @returns    Gap&      
00223 */
00224 /**************************************************************************/
00225 Gap        &BlueNRGDevice::getGap()        
00226 {
00227     return BlueNRGGap::getInstance();
00228 }
00229 
00230 const Gap  &BlueNRGDevice::getGap() const        
00231 {
00232     return BlueNRGGap::getInstance();
00233 }
00234 
00235 /**************************************************************************/
00236 /*!
00237     @brief  get reference to GATT server object
00238     @param[in] void
00239     @returns    GattServer&    
00240 */
00241 /**************************************************************************/
00242 GattServer &BlueNRGDevice::getGattServer() 
00243 {
00244     return BlueNRGGattServer::getInstance();
00245 }
00246 
00247 const GattServer &BlueNRGDevice::getGattServer() const
00248 {
00249     return BlueNRGGattServer::getInstance();
00250 }
00251  
00252 /**************************************************************************/
00253 /*!
00254     @brief  shut down the the BLE device
00255     @param[out] error if any
00256 */
00257 /**************************************************************************/
00258 ble_error_t  BlueNRGDevice::shutdown(void) {
00259     return reset();
00260 }
00261                                                                                             
00262 /**
00263  * @brief  Reads from BlueNRG SPI buffer and store data into local buffer.
00264  * @param  buffer   : Buffer where data from SPI are stored
00265  * @param  buff_size: Buffer size
00266  * @retval int32_t  : Number of read bytes
00267  */
00268 int32_t BlueNRGDevice::spiRead(uint8_t *buffer, uint8_t buff_size)
00269 {
00270   uint16_t byte_count;
00271   uint8_t len = 0;
00272   uint8_t char_ff = 0xff;
00273   volatile uint8_t read_char;
00274     
00275     uint8_t i = 0;
00276     volatile uint8_t tmpreg;
00277 
00278   uint8_t header_master[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00};
00279   uint8_t header_slave[HEADER_SIZE];
00280 
00281   /* Select the chip */
00282   nCS_ = 0;
00283     
00284   /* Read the header */  
00285   for (i = 0; i < 5; i++)
00286   { 
00287         tmpreg = spi_.write(header_master[i]);
00288         header_slave[i] = (uint8_t)(tmpreg);
00289   } 
00290     
00291   if (header_slave[0] == 0x02) {
00292     /* device is ready */
00293     byte_count = (header_slave[4]<<8)|header_slave[3];
00294   
00295     if (byte_count > 0) {
00296   
00297       /* avoid to read more data that size of the buffer */
00298       if (byte_count > buff_size){
00299         byte_count = buff_size;
00300       }
00301   
00302       for (len = 0; len < byte_count; len++){
00303         read_char = spi_.write(char_ff);
00304                 buffer[len] = read_char;
00305       }
00306     }    
00307   }
00308   /* Release CS line to deselect the chip */
00309   nCS_ = 1;
00310     
00311   // Add a small delay to give time to the BlueNRG to set the IRQ pin low
00312   // to avoid a useless SPI read at the end of the transaction
00313   for(volatile int i = 0; i < 2; i++)__NOP();
00314   
00315 #ifdef PRINT_CSV_FORMAT
00316   if (len > 0) {
00317     print_csv_time();
00318     for (int i=0; i<len; i++) {
00319       PRINT_CSV(" %02x", buffer[i]);
00320     }
00321     PRINT_CSV("\n");
00322   }
00323 #endif
00324   
00325   return len;   
00326 }
00327 
00328 /**
00329  * @brief  Writes data from local buffer to SPI.
00330  * @param  data1    : First data buffer to be written
00331  * @param  data2    : Second data buffer to be written
00332  * @param  Nb_bytes1: Size of first data buffer to be written
00333  * @param  Nb_bytes2: Size of second data buffer to be written
00334  * @retval Number of read bytes
00335  */
00336 int32_t BlueNRGDevice::spiWrite(uint8_t* data1,
00337                 uint8_t* data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2)
00338 {  
00339     int32_t result = 0;
00340     uint32_t i;
00341     volatile uint8_t tmpreg;
00342     
00343   unsigned char header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00};
00344   unsigned char header_slave[HEADER_SIZE]  = {0xaa, 0x00, 0x00, 0x00, 0x00};
00345 
00346   disable_irq();
00347 
00348   /* CS reset */
00349   nCS_ = 0;
00350 
00351   /* Exchange header */  
00352   for (i = 0; i < 5; i++)
00353   { 
00354         tmpreg = spi_.write(header_master[i]);
00355         header_slave[i] = tmpreg;
00356   } 
00357     
00358   if (header_slave[0] == 0x02) {
00359     /* SPI is ready */
00360     if (header_slave[1] >= (Nb_bytes1+Nb_bytes2)) {
00361   
00362       /*  Buffer is big enough */
00363             for (i = 0; i < Nb_bytes1; i++) {
00364                 spi_.write(*(data1 + i));
00365       }
00366       for (i = 0; i < Nb_bytes2; i++) {
00367                 spi_.write(*(data2 + i));
00368       }         
00369     } else {
00370       /* Buffer is too small */
00371       result = -2;
00372     }
00373   } else {
00374     /* SPI is not ready */
00375     result = -1;
00376   }
00377     
00378   /* Release CS line */
00379   //HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET);
00380   nCS_ = 1;
00381             
00382   enable_irq();
00383     
00384   return result;
00385 }
00386 
00387 bool BlueNRGDevice::dataPresent()
00388 {
00389     return (irq_ == 1);
00390 }
00391 
00392 void BlueNRGDevice::disable_irq()
00393 {
00394     irq_.disable_irq();
00395 }
00396 
00397 void BlueNRGDevice::enable_irq()
00398 {
00399     irq_.enable_irq();
00400 }