Merck / Mbed OS SmartCap_OS5

Dependencies:   nRF51822

Source/BLE_Stuff.cpp

Committer:
sgetz7908
Date:
2019-03-19
Revision:
23:7ca590427f0e
Child:
24:761c30334cf4

File content as of revision 23:7ca590427f0e:


/// @file BLE_Stuff.cpp
#include <events/mbed_events.h>
#include <mbed.h>
#include "ble/BLE.h"
#include "ble/Gap.h"
#include "ble/services/UARTService.h"
#include <ctype.h>

#include "BLE_Stuff.h"
#include "infoService.h"
#include "hw.h"
#include "log.h"
#include "main.h"
#include "log.h"
#include "nrf_soc.h"

extern EventQueue eventQueue; //(/* event count */ 16 * EVENTS_EVENT_SIZE);
UARTService *uartServicePtr = NULL;

LowPowerTimeout bleInactivity_timeout;


int adv_timeout_ID = 0;

int adv_state = false;
char dev_name[15] = "";

volatile int batt_voltage = 0; // actual battery voltage * 100

bool m_isConnected = false;

void process_cmd(char * cmd);


/// Called by bleInactivity_timeout
void disconnect(void)
{
    bleInactivity_timeout.detach();
#if UART_DEBUGGING==0
    BLE &ble = BLE::Instance();
    ble.gap().disconnect(Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF); // force disconnect
#endif
}

void reset_ble_activity_timer(void)
{
    bleInactivity_timeout.detach();
    bleInactivity_timeout.attach(&disconnect, BLE_INACTIVITY_TIMEOUT);
}

/// Called when the Bluetooth connection is disconnected.
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    m_isConnected = false;
    bleInactivity_timeout.detach();
    BLE &ble = BLE::Instance();
    ble.gap().setAdvertisingInterval(ADV_INTERVAL);
    if(adv_state) ble.gap().startAdvertising();
}

void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
    m_isConnected = true;
    BLE &ble = BLE::Instance();
    ble.gap().setAdvertisingInterval(CONN_INTERVAL);
    reset_ble_activity_timer();   
}

bool isConnected(void)
{
    return m_isConnected;
}

/// Called to write a string to the Bluetooth UART.
// used for writting to the BLE UART
void BLE_UART_xmit(const char * str)
{
    if (uartServicePtr != NULL) {
        uartServicePtr->writeString(str);
    }
}

void BLE_UART_xmit(int i)
{
    BLE_UART_xmit(uli2a(i));
}

char cmd_str[21];

/// Called when data is rcv'd from connected BLE device
void onDataWritten(const GattWriteCallbackParams *params)
{
    if ((uartServicePtr != NULL) && (params->handle == uartServicePtr->getTXCharacteristicHandle())) {
        uint16_t bytesRead = params->len;
        strncpy(cmd_str, (const char *)params->data, bytesRead);
        
        // Start process: process_cmd(cmd_str) as regular non-irq routine
        eventQueue.call(process_cmd, cmd_str);
        // the dispatch method executes events
        //queue.dispatch();
        
        //ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead); // send back whatever is sent to us
        reset_ble_activity_timer();
    }
}

/// Turn on or off advertising
// When turned on, it will only advertise for a limited time, or until turned off.
void set_radio(int state)
{
    BLE &ble = BLE::Instance();
    adv_state = state;

    if(state) {
        adv_state = true;
        ble.gap().setAdvertisingInterval(ADV_INTERVAL);
        ble.gap().startAdvertising();
    } else {
        adv_state = false;
        ble.gap().stopAdvertising();
        disconnect();
    }
}

#if 0
void stop_radio_and_wait(void)
{
    set_radio(false);
    
    // If radio is active, wait for it to become inactive.
    //wait(0.5);
    while (isConnected())// || isRadioActive())
    {
        // Do nothing (just wait for radio to become inactive).
         sd_app_evt_wait();
    }
}
#endif

ble_init_status_t ble_init_status = BLE_INIT_IN_PROGRESS;
    
/// Called to setup the Bluetooth link.
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        ble_init_status = BLE_INIT_ERROR;
        return;
    }

    /* Ensure that it is the default instance of BLE */
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    ble.gap().onDisconnection(disconnectionCallback);
    ble.gap().onConnection(connectionCallback);
    ble.gattServer().onDataWritten(onDataWritten);

    //ble.gattServer().onDataRead( dataReadCallback ); //const DataReadCallback_t & callback)
    //ble.onDataRead( dataReadCallback);

    strcpy(dev_name, DEV_NAME);
    strcat(dev_name, char2hex(NRF_FICR->DEVICEADDR[0] & 0xff));
    int len = strlen(dev_name);

    ble.gap().setDeviceName((std::uint8_t *)dev_name);
    
    /* Setup primary service */
    uartServicePtr = new UARTService(ble);

    /* setup advertising */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
                                     (const uint8_t *)dev_name, len);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                     (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));


    ble.gap().setAdvertisingInterval(ADV_INTERVAL);
    ble.gap().setAdvertisingTimeout(BLE_ADVERTISING_DURATION);
    ble.gap().setTxPower(-20); // -30, -20, -16, -12, -8, -4, 0, and 4 dBm

    ble_init_status = BLE_INIT_OK;

    set_radio(true);
}

/// Process BLE Events
void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
    BLE &ble = BLE::Instance();
    eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
}

/// Initialize the BLE Stack
// Returns 0 if OK
ble_init_status_t Init_BLE_Stuff(void)
{
    ble_init_status = BLE_INIT_IN_PROGRESS;
    BLE &ble = BLE::Instance();
    ble.onEventsToProcess(scheduleBleEventsProcessing);
    ble.init(bleInitComplete);

    // Wait for initialization to complete. This is necessary because the
    // BLE object is used after this.
    while(ble_init_status == BLE_INIT_IN_PROGRESS) { wait(0.05);}
    // set up BLE Information services in infoService.cpp
    //ble.gattServer().addService(infoServicePtr);
    return ble_init_status;
}