WILLIAN MATTOS / X_NUCLEO_IDB0XA1

Dependents:   BLE_HeartRate_IDB0XA1

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     #include "bluenrg_utils.h"
00055 }
00056 
00057 #define HEADER_SIZE 5
00058 #define MAX_BUFFER_SIZE 255
00059 
00060 /**
00061  * The singleton which represents the BlueNRG transport for the BLEDevice.
00062  *
00063  * See file 'x_nucleo_idb0xa1_targets.h' for details regarding the peripheral pins used!
00064  */
00065 #include "x_nucleo_idb0xa1_targets.h"
00066 
00067 BlueNRGDevice bluenrgDeviceInstance(IDB0XA1_PIN_SPI_MOSI,
00068                                     IDB0XA1_PIN_SPI_MISO,
00069                                     IDB0XA1_PIN_SPI_SCK,
00070                                     IDB0XA1_PIN_SPI_nCS,
00071                                     IDB0XA1_PIN_SPI_RESET,
00072                                     IDB0XA1_PIN_SPI_IRQ);
00073 
00074 /**
00075 * BLE-API requires an implementation of the following function in order to
00076 * obtain its transport handle.
00077 */
00078 BLEInstanceBase *
00079 createBLEInstance(void)
00080 {
00081     return (&bluenrgDeviceInstance);
00082 }
00083 
00084 /**************************************************************************/
00085 /**
00086     @brief  Constructor
00087      * @param mosi mbed pin to use for MOSI line of SPI interface
00088      * @param miso mbed pin to use for MISO line of SPI interface
00089      * @param sck mbed pin to use for SCK line of SPI interface
00090      * @param cs mbed pin to use for not chip select line of SPI interface
00091      * @param rst mbed pin to use for BlueNRG reset
00092      * @param irq mbed pin for BlueNRG IRQ
00093 */
00094 /**************************************************************************/
00095 BlueNRGDevice::BlueNRGDevice(PinName mosi,
00096                              PinName miso,
00097                              PinName sck,
00098                              PinName cs,
00099                              PinName rst,
00100                              PinName irq) : 
00101     isInitialized(false), spi_(mosi, miso, sck), nCS_(cs), rst_(rst), irq_(irq)
00102 {
00103     // Setup the spi for 8 bit data, low clock polarity,
00104     // 1-edge phase, with an 8MHz clock rate
00105     spi_.format(8, 0);
00106     spi_.frequency(8000000);
00107     
00108     // Deselect the BlueNRG chip by keeping its nCS signal high
00109     nCS_ = 1;
00110 
00111     wait_us(500);
00112 
00113     // Prepare communication between the host and the BlueNRG SPI interface
00114     HCI_Init();
00115 
00116     // Set the interrupt handler for the device
00117     irq_.mode(PullDown); // set irq mode
00118     irq_.rise(&HCI_Isr);
00119 }
00120 
00121 /**************************************************************************/
00122 /**
00123     @brief  Destructor
00124 */
00125 /**************************************************************************/
00126 BlueNRGDevice::~BlueNRGDevice(void)
00127 {
00128 }
00129 
00130 /**
00131   * @brief  Get BlueNRG HW version in bootloader mode
00132   * @param  hw_version The HW version is written to this parameter
00133   * @retval It returns BLE_STATUS_SUCCESS on success or an error code otherwise
00134   */
00135 uint8_t BlueNRGDevice::getUpdaterHardwareVersion(uint8_t *hw_version)
00136 {
00137     uint8_t status;
00138 
00139     status = getBlueNRGUpdaterHWVersion(hw_version);
00140 
00141     return (status);
00142 }
00143 
00144 /**
00145   * @brief  Flash a new firmware using internal bootloader.
00146   * @param  fw_image     Pointer to the firmware image (raw binary data,
00147   *                      little-endian).
00148   * @param  fw_size      Size of the firmware image. The firmware image size shall
00149   *                      be multiple of 4 bytes.
00150   * @retval int      It returns BLE_STATUS_SUCCESS on success, or a number
00151   *                  not equal to 0 in case of error
00152   *                  (ACI_ERROR, UNSUPPORTED_VERSION, WRONG_IMAGE_SIZE, CRC_ERROR)
00153   */
00154 int BlueNRGDevice::updateFirmware(const uint8_t *fw_image, uint32_t fw_size)
00155 {
00156     int status = program_device(fw_image, fw_size);
00157     
00158     return (status);
00159 }
00160 
00161 
00162 /**
00163   * @brief  Initialises anything required to start using BLE
00164   * @param[in] instanceID
00165   *              The ID of the instance to initialize.
00166   * @param[in] callback
00167   *              A callback for when initialization completes for a BLE
00168   *              instance. This is an optional parameter set to NULL when not
00169   *              supplied.
00170   *
00171   * @return BLE_ERROR_NONE if the initialization procedure was started
00172   *         successfully.
00173   */
00174 ble_error_t BlueNRGDevice::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback)
00175 {
00176     if (isInitialized) {
00177             BLE::InitializationCompleteCallbackContext context = {
00178                 BLE::Instance(instanceID),
00179                 BLE_ERROR_ALREADY_INITIALIZED
00180             };
00181             callback.call(&context);
00182             return BLE_ERROR_ALREADY_INITIALIZED;
00183         }
00184     
00185     /* ToDo: Clear memory contents, reset the SD, etc. */
00186     // Init the BlueNRG/BlueNRG-MS stack
00187     // By default, we set the device GAP role to PERIPHERAL
00188     btleInit(BlueNRGGap::getInstance().getIsSetAddress(), GAP_PERIPHERAL_ROLE_IDB04A1);
00189     
00190     isInitialized = true;
00191     BLE::InitializationCompleteCallbackContext context = {
00192             BLE::Instance(instanceID),
00193             BLE_ERROR_NONE
00194     };
00195     callback.call(&context);
00196     
00197     return BLE_ERROR_NONE;
00198 }
00199 
00200 
00201 /**
00202     @brief  Resets the BLE HW, removing any existing services and
00203             characteristics
00204     @param[in] void
00205     @returns    void
00206 */
00207 void BlueNRGDevice::reset(void)
00208 {
00209     wait_us(500);
00210 
00211     /* Reset BlueNRG SPI interface */
00212       rst_ = 0;
00213     wait_us(5);
00214       rst_ = 1;
00215     wait_us(5);
00216 
00217     /* Wait for the radio to come back up */
00218     wait_us(500);
00219 
00220 }
00221 
00222 /*!
00223   @brief  Wait for any BLE Event like BLE Connection, Read Request etc.    
00224   @param[in] void
00225   @returns    char *      
00226 */
00227 void BlueNRGDevice::waitForEvent(void)
00228 {
00229     bool must_return = false;
00230 
00231     do {
00232         BlueNRGGap::getInstance().Process();
00233         
00234         HCI_Process();
00235         
00236         if(must_return) return;
00237 
00238         __WFE(); /* it is recommended that SEVONPEND in the
00239                 System Control Register is NOT set */
00240         must_return = true; /* after returning from WFE we must guarantee
00241                        that conrol is given back to main loop before next WFE */
00242     } while(true);
00243 
00244 } 
00245  
00246 /*!
00247     @brief  get GAP version
00248     @brief Get the BLE stack version information
00249     @param[in] void
00250     @returns    char *
00251     @returns char *
00252 */
00253 const char *BlueNRGDevice::getVersion(void)
00254 {
00255     return getVersionString();
00256 }
00257 
00258 /**************************************************************************/
00259 /*!
00260     @brief  get reference to GAP object
00261     @param[in] void
00262     @returns    Gap&      
00263 */
00264 /**************************************************************************/
00265 Gap        &BlueNRGDevice::getGap()        
00266 {
00267     return BlueNRGGap::getInstance();
00268 }
00269 
00270 const Gap  &BlueNRGDevice::getGap() const        
00271 {
00272     return BlueNRGGap::getInstance();
00273 }
00274 
00275 /**************************************************************************/
00276 /*!
00277     @brief  get reference to GATT server object
00278     @param[in] void
00279     @returns    GattServer&    
00280 */
00281 /**************************************************************************/
00282 GattServer &BlueNRGDevice::getGattServer() 
00283 {
00284     return BlueNRGGattServer::getInstance();
00285 }
00286 
00287 const GattServer &BlueNRGDevice::getGattServer() const
00288 {
00289     return BlueNRGGattServer::getInstance();
00290 }
00291  
00292 /**************************************************************************/
00293 /*!
00294     @brief  shut down the BLE device
00295     @param[out] error if any
00296 */
00297 /**************************************************************************/
00298 ble_error_t  BlueNRGDevice::shutdown(void) {
00299     if (!isInitialized) {
00300         return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00301     }
00302 
00303     /* Reset the BlueNRG device first */
00304     reset();
00305 
00306     /* Shutdown the BLE API and BlueNRG glue code */
00307     ble_error_t error;
00308 
00309     /* GattServer instance */
00310     error = BlueNRGGattServer::getInstance().reset();
00311     if (error != BLE_ERROR_NONE) {
00312        return error;
00313     }
00314 
00315     /* GattClient instance */
00316     error = BlueNRGGattClient::getInstance().reset();
00317     if (error != BLE_ERROR_NONE) {
00318         return error;
00319     }
00320 
00321     /* Gap instance */
00322     error = BlueNRGGap::getInstance().reset();
00323     if (error != BLE_ERROR_NONE) {
00324         return error;
00325     }
00326 
00327     isInitialized = false;
00328 
00329     return BLE_ERROR_NONE;
00330 
00331 }
00332                                                                                             
00333 /**
00334  * @brief  Reads from BlueNRG SPI buffer and store data into local buffer.
00335  * @param  buffer   : Buffer where data from SPI are stored
00336  * @param  buff_size: Buffer size
00337  * @retval int32_t  : Number of read bytes
00338  */
00339 int32_t BlueNRGDevice::spiRead(uint8_t *buffer, uint8_t buff_size)
00340 {
00341   uint16_t byte_count;
00342   uint8_t len = 0;
00343   uint8_t char_ff = 0xff;
00344   volatile uint8_t read_char;
00345     
00346     uint8_t i = 0;
00347     volatile uint8_t tmpreg;
00348 
00349   uint8_t header_master[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00};
00350   uint8_t header_slave[HEADER_SIZE];
00351 
00352   /* Select the chip */
00353   nCS_ = 0;
00354     
00355   /* Read the header */  
00356   for (i = 0; i < 5; i++)
00357   { 
00358         tmpreg = spi_.write(header_master[i]);
00359         header_slave[i] = (uint8_t)(tmpreg);
00360   } 
00361     
00362   if (header_slave[0] == 0x02) {
00363     /* device is ready */
00364     byte_count = (header_slave[4]<<8)|header_slave[3];
00365   
00366     if (byte_count > 0) {
00367   
00368       /* avoid to read more data that size of the buffer */
00369       if (byte_count > buff_size){
00370         byte_count = buff_size;
00371       }
00372   
00373       for (len = 0; len < byte_count; len++){
00374         read_char = spi_.write(char_ff);
00375                 buffer[len] = read_char;
00376       }
00377     }    
00378   }
00379   /* Release CS line to deselect the chip */
00380   nCS_ = 1;
00381     
00382   // Add a small delay to give time to the BlueNRG to set the IRQ pin low
00383   // to avoid a useless SPI read at the end of the transaction
00384   for(volatile int i = 0; i < 2; i++)__NOP();
00385   
00386 #ifdef PRINT_CSV_FORMAT
00387   if (len > 0) {
00388     print_csv_time();
00389     for (int i=0; i<len; i++) {
00390       PRINT_CSV(" %02x", buffer[i]);
00391     }
00392     PRINT_CSV("\n");
00393   }
00394 #endif
00395   
00396   return len;   
00397 }
00398 
00399 /**
00400  * @brief  Writes data from local buffer to SPI.
00401  * @param  data1    : First data buffer to be written
00402  * @param  data2    : Second data buffer to be written
00403  * @param  Nb_bytes1: Size of first data buffer to be written
00404  * @param  Nb_bytes2: Size of second data buffer to be written
00405  * @retval Number of read bytes
00406  */
00407 int32_t BlueNRGDevice::spiWrite(uint8_t* data1,
00408                 uint8_t* data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2)
00409 {  
00410     int32_t result = 0;
00411     uint32_t i;
00412     volatile uint8_t tmpreg;
00413     
00414   unsigned char header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00};
00415   unsigned char header_slave[HEADER_SIZE]  = {0xaa, 0x00, 0x00, 0x00, 0x00};
00416 
00417   disable_irq();
00418 
00419   /* CS reset */
00420   nCS_ = 0;
00421 
00422   /* Exchange header */  
00423   for (i = 0; i < 5; i++)
00424   { 
00425         tmpreg = spi_.write(header_master[i]);
00426         header_slave[i] = tmpreg;
00427   } 
00428     
00429   if (header_slave[0] == 0x02) {
00430     /* SPI is ready */
00431     if (header_slave[1] >= (Nb_bytes1+Nb_bytes2)) {
00432   
00433       /*  Buffer is big enough */
00434             for (i = 0; i < Nb_bytes1; i++) {
00435                 spi_.write(*(data1 + i));
00436       }
00437       for (i = 0; i < Nb_bytes2; i++) {
00438                 spi_.write(*(data2 + i));
00439       }         
00440     } else {
00441       /* Buffer is too small */
00442       result = -2;
00443     }
00444   } else {
00445     /* SPI is not ready */
00446     result = -1;
00447   }
00448     
00449   /* Release CS line */
00450   //HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET);
00451   nCS_ = 1;
00452             
00453   enable_irq();
00454     
00455   return result;
00456 }
00457 
00458 bool BlueNRGDevice::dataPresent()
00459 {
00460     return (irq_ == 1);
00461 }
00462 
00463 void BlueNRGDevice::disable_irq()
00464 {
00465     irq_.disable_irq();
00466 }
00467 
00468 void BlueNRGDevice::enable_irq()
00469 {
00470     irq_.enable_irq();
00471 }