HW layer for the Nucleo board, it only work with old BLE_API
Dependents: Hello_BLE F446RE-BLE
Fork of X_NUCLEO_IDB0XA1 by
BlueNRGDevice.cpp
- Committer:
- Wolfgang Betz
- Date:
- 2015-08-11
- Revision:
- 112:6dc0ad44750d
- Parent:
- 103:12684d94c3a6
- Child:
- 113:31c73e9b0108
File content as of revision 112:6dc0ad44750d:
/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** ****************************************************************************** * @file BlueNRGDevice.cpp * @author STMicroelectronics * @brief Implementation of BLEDeviceInstanceBase ****************************************************************************** * @copy * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> */ /** @defgroup BlueNRGDevice * @brief BlueNRG BLE_API Device Adaptation * @{ */ #include "mbed.h" #include "BlueNRGDevice.h" #include "BlueNRGGap.h" #include "BlueNRGGattServer.h" #include "btle.h" #include "Utils.h" #include "osal.h" extern "C" { #include "hci.h" } #define HEADER_SIZE 5 #define MAX_BUFFER_SIZE 255 /** * The singleton which represents the BlueNRG transport for the BLEDevice. * FIXME: find a better way to create the BlueNRG device instance so that * the pin names can be chosen by the users of this class * * This is using Arduino pins as follows: * D11: MOSI line of SPI interface * D12: MISO line of SPI interface * D3 : SCK line of SPI interface * A1 : nCS line of SPI interface * D7 : BlueNRG reset * A0 : BlueNRG IRQ pin */ BlueNRGDevice bluenrgDeviceInstance(D11, D12, D3, A1, D7, A0); /** * BLE-API requires an implementation of the following function in order to * obtain its transport handle. */ BLEInstanceBase * createBLEInstance(void) { return (&bluenrgDeviceInstance); } /**************************************************************************/ /** @brief Constructor * @param mosi mbed pin to use for MOSI line of SPI interface * @param miso mbed pin to use for MISO line of SPI interface * @param sck mbed pin to use for SCK line of SPI interface * @param cs mbed pin to use for not chip select line of SPI interface * @param rst mbed pin to use for BlueNRG reset * @param irq mbed pin for BlueNRG IRQ */ /**************************************************************************/ BlueNRGDevice::BlueNRGDevice(PinName mosi, PinName miso, PinName sck, PinName cs, PinName rst, PinName irq) : spi_(mosi, miso, sck), nCS_(cs), rst_(rst), irq_(irq) { isInitialized = false; // Setup the spi for 8 bit data, low clock polarity, // 1-edge phase, with an 8MHz clock rate spi_.format(8, 0); spi_.frequency(8000000); // Deselect the BlueNRG chip by keeping its nCS signal high nCS_ = 1; wait_us(500); } /**************************************************************************/ /** @brief Destructor */ /**************************************************************************/ BlueNRGDevice::~BlueNRGDevice(void) { } /** @brief Initialises anything required to start using BLE @param[in] void @returns ble_error_t */ ble_error_t BlueNRGDevice::init(void) { // Set the interrupt handler for the device irq_.rise(&HCI_Isr); /* ToDo: Clear memory contents, reset the SD, etc. */ btle_init(BlueNRGGap::getInstance().getIsSetAddress()); isInitialized = true; return BLE_ERROR_NONE; } /** @brief Resets the BLE HW, removing any existing services and characteristics @param[in] void @returns ble_error_t */ ble_error_t BlueNRGDevice::reset(void) { wait_us(500); /* Reset BlueNRG SPI interface */ rst_ = 0; wait_us(5); rst_ = 1; wait_us(5); /* Wait for the radio to come back up */ wait_us(500); isInitialized = false; return BLE_ERROR_NONE; } /*! @brief Wait for any BLE Event like BLE Connection, Read Request etc. @param[in] void @returns char * */ void BlueNRGDevice::waitForEvent(void) { bool must_return = false; do { HCI_Process(); if(must_return) return; __WFE(); /* it is recommended that SEVONPEND in the System Control Register is NOT set */ must_return = true; /* after returning from WFE we must guarantee that conrol is given back to main loop before next WFE */ } while(true); } /*! @brief get GAP version @param[in] void @returns char * */ const char *BlueNRGDevice::getVersion(void) { char *version = new char[6]; memcpy((void *)version, "1.0.0", 5); return version; } /**************************************************************************/ /*! @brief get init state @param[in] void @returns bool */ /**************************************************************************/ bool BlueNRGDevice::getIsInitialized(void) { return isInitialized; } /**************************************************************************/ /*! @brief get reference to GAP object @param[in] void @returns Gap& */ /**************************************************************************/ Gap &BlueNRGDevice::getGap() { return BlueNRGGap::getInstance(); } const Gap &BlueNRGDevice::getGap() const { return BlueNRGGap::getInstance(); } /**************************************************************************/ /*! @brief get reference to GATT server object @param[in] void @returns GattServer& */ /**************************************************************************/ GattServer &BlueNRGDevice::getGattServer() { return BlueNRGGattServer::getInstance(); } const GattServer &BlueNRGDevice::getGattServer() const { return BlueNRGGattServer::getInstance(); } /**************************************************************************/ /*! @brief shut down the the BLE device @param[out] error if any */ /**************************************************************************/ ble_error_t BlueNRGDevice::shutdown(void) { return reset(); } /** * @brief Reads from BlueNRG SPI buffer and store data into local buffer. * @param buffer : Buffer where data from SPI are stored * @param buff_size: Buffer size * @retval int32_t : Number of read bytes */ int32_t BlueNRGDevice::spiRead(uint8_t *buffer, uint8_t buff_size) { uint16_t byte_count; uint8_t len = 0; uint8_t char_ff = 0xff; volatile uint8_t read_char; uint8_t i = 0; volatile uint8_t tmpreg; uint8_t header_master[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00}; uint8_t header_slave[HEADER_SIZE]; /* Select the chip */ nCS_ = 0; /* Read the header */ for (i = 0; i < 5; i++) { tmpreg = spi_.write(header_master[i]); header_slave[i] = (uint8_t)(tmpreg); } if (header_slave[0] == 0x02) { /* device is ready */ byte_count = (header_slave[4]<<8)|header_slave[3]; if (byte_count > 0) { /* avoid to read more data that size of the buffer */ if (byte_count > buff_size){ byte_count = buff_size; } for (len = 0; len < byte_count; len++){ read_char = spi_.write(char_ff); buffer[len] = read_char; } } } /* Release CS line to deselect the chip */ nCS_ = 1; // Add a small delay to give time to the BlueNRG to set the IRQ pin low // to avoid a useless SPI read at the end of the transaction for(volatile int i = 0; i < 2; i++)__NOP(); #ifdef PRINT_CSV_FORMAT if (len > 0) { // print_csv_time(); for (int i=0; i<len; i++) { PRINT_CSV(" %02x", buffer[i]); } PRINT_CSV("\n"); } #endif return len; } /** * @brief Writes data from local buffer to SPI. * @param data1 : First data buffer to be written * @param data2 : Second data buffer to be written * @param Nb_bytes1: Size of first data buffer to be written * @param Nb_bytes2: Size of second data buffer to be written * @retval Number of read bytes */ int32_t BlueNRGDevice::spiWrite(uint8_t* data1, uint8_t* data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2) { int32_t result = 0; uint32_t i; volatile uint8_t tmpreg; unsigned char header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00}; unsigned char header_slave[HEADER_SIZE] = {0xaa, 0x00, 0x00, 0x00, 0x00}; //unsigned char read_char_buf[MAX_BUFFER_SIZE]; disable_irq(); /* CS reset */ nCS_ = 0; /* Exchange header */ for (i = 0; i < 5; i++) { tmpreg = spi_.write(header_master[i]); header_slave[i] = tmpreg; } if (header_slave[0] == 0x02) { /* SPI is ready */ if (header_slave[1] >= (Nb_bytes1+Nb_bytes2)) { /* Buffer is big enough */ for (i = 0; i < Nb_bytes1; i++) { spi_.write(*(data1 + i)); } for (i = 0; i < Nb_bytes2; i++) { spi_.write(*(data2 + i)); } } else { /* Buffer is too small */ result = -2; } } else { /* SPI is not ready */ result = -1; } /* Release CS line */ //HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); nCS_ = 1; enable_irq(); return result; } bool BlueNRGDevice::dataPresent() { return (irq_ == 1); } void BlueNRGDevice::disable_irq() { irq_.disable_irq(); } void BlueNRGDevice::enable_irq() { irq_.enable_irq(); }