We are making a bluetooth application for a vehicle.

Dependencies:   BLE_API X_NUCLEO_IDB0XA1 mbed

Fork of BLE_HeartRate_IDB0XA1 by ST

main.cpp

Committer:
bobbaddeley
Date:
2017-07-19
Revision:
30:243e095a69d9
Parent:
29:e7d4922a4620

File content as of revision 30:243e095a69d9:

/* mbed Microcontroller Library
 * Copyright (c) 2006-2015 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.
 */

#include "mbed.h"
#include "ble/BLE.h"
#include "bike_service.h"
#include "ble/services/BatteryService.h"

int alarm_activated = 0;
int alarm_on = 0;
int alarm_counter = 0;

DigitalOut led_0(PC_6);
DigitalOut led_1(PC_7);
DigitalOut buzzer(PC_8);
DigitalOut rumblr(PC_9);;
DigitalOut led1(LED1, 1);

const static char     DEVICE_NAME[]        = "HeckBike!";
static const uint16_t uuid16_list[]        = {GattService::UUID_BATTERY_SERVICE,
                                              0x8EC5};//made up UUID for the Heck bike

#define on  0xFFFF
#define off 0
 
#define buttonMask 0x003F
 
PortIn sixButtons(PortC, buttonMask);

//InterruptIn event(sixButtons.read());
//InterruptIn interruptEventButton_0(PC_2);
//InterruptIn interruptEventButton_1(PC_3);
//InterruptIn interruptEventButton_2(PC_4);
//InterruptIn interruptEventButton_3(PC_5);
//InterruptIn interruptEventSensor_0(PC_0); // Vibration
//InterruptIn interruptEventSensor_1(PC_1); // Tilt

unsigned char byteIn = 0; 
unsigned char prevByteIn = 0;

uint8_t inputs = 0x00;
uint8_t outputs = 0x00;
uint8_t old_outputs = 0x00;
uint32_t timestamp = 0x00;
    
static volatile bool  triggerSensorPolling = false;

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    (void)params;
    BLE::Instance().gap().startAdvertising(); // restart advertising
}

void toggleLED(void)
{
    led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
}

void periodicCallback(void)
{
    /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
     * heavy-weight sensor polling from the main thread. */
    triggerSensorPolling = true;
}

void onBleInitError(BLE &ble, ble_error_t error)
{
    (void)ble;
    (void)error;
   /* Initialization error handling should go here */
}

void onDataWrittenCallback(const GattWriteCallbackParams *params) {
    //if (params->handle == BikeService.output_characteristic.getValueAttribute().getHandle()) {
        outputs = *(params->data);
        if (outputs & 0x01){
            led_0 = 1;
        }
        if ((outputs & 0x01) == 0){
            led_0 = 0;
        }
            
        if (outputs & 0x02){
            led_1 = 1;
        }
        if ((outputs & 0x02) == 0){
            led_1 = 0;
        }
            
        if (outputs & 0x04){
            buzzer = 1;
            }
        if ((outputs & 0x04) == 0){
            buzzer = 0;
        }
            
        if (outputs & 0x08){
            rumblr = 1;
        }
        if ((outputs & 0x08) == 0){
            rumblr = 0;
        }
            
        if (outputs & 0x10){
            alarm_activated = 1;
        }
        if ((outputs & 0x10) == 0){
            alarm_activated = 0;
            alarm_on = 0;
        }
        
        if (outputs & 0x20){
            alarm_on = 1;
        }
        if ((outputs & 0x20) == 0){
            alarm_on = 0;
        }
    //}
}

void alarm() {
     if (alarm_activated && alarm_on) {                                        //Flag set to sound the alarm?
            
            if (alarm_counter++ < 500) {                            //Beep it on and off
                buzzer = 1;
                led_0 = 1;
                led_1 = 1;
                rumblr = 1;
            }
            else {
                if (alarm_counter > 1000){alarm_counter = 0;}
                buzzer = 0;
                led_0 = 0;
                led_1 = 0;
                rumblr = 0;
            }
        }
}

//void interruptButton_0() {

//} 
//void interruptButton_1() {
    
//}
//void interruptButton_2() {

//} 
//void interruptButton_3() {
    
//}  
//void interruptSensor_0() { // Vibration
//    alarm_on = 1;
//} 
//void interruptSensor_1() { // Tilt
//    
//}
 
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        onBleInitError(ble, error);
        return;
    }

    if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    ble.gap().onDisconnection(disconnectionCallback);

    ble.gattServer().onDataWritten(onDataWrittenCallback);
    /* Setup primary service. */
    BikeService bikeService(ble);
    /* Setup battery service. */
    BatteryService btService(ble,100);
    /* Setup advertising. */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_CYCLING);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(1000); /* 1000ms */
    ble.gap().startAdvertising();

    // infinite loop
    while (true) {
        // check for trigger from periodicCallback()
        if (triggerSensorPolling && ble.getGapState().connected) {
        //if (ble.getGapState().connected) {
            
            
            triggerSensorPolling = false;
            byteIn = sixButtons & buttonMask;
            // update the ble with the inputs
            //bikeService.updateInputs(byteOut);
            //bikeService.updateTimestamp();
            if (((byteIn & 0x01)==0) && alarm_activated==1 && alarm_on==0) {
                alarm_on = 1;
                outputs = outputs | 0x20;
                bikeService.updateOutputs(outputs);
             }
            if (byteIn != prevByteIn){
                // update the ble with the inputs
                bikeService.updateInputs(byteIn);
                bikeService.updateTimestamp();
            }
            prevByteIn = byteIn;
             
        } else {
            ble.waitForEvent(); // low power wait for event
        }
        
        alarm();     
    }
}

int main(void)
{
    
    //interruptEventButton_0.fall(&interruptButton_0);
    //interruptEventButton_1.fall(&interruptButton_1);
    //interruptEventButton_2.fall(&interruptButton_2);
    //interruptEventButton_3.fall(&interruptButton_3);
    //interruptEventSensor_0.fall(&interruptSensor_0); // Vibration
    //interruptEventSensor_1.fall(&interruptSensor_1); // Tilt
    
    Ticker ticker;
    ticker.attach(toggleLED, 1);
    
    Ticker ticker_CallBack;
    //ticker.attach(periodicCallback, 1); // blink LED every second
    ticker_CallBack.attach(periodicCallback, 0.1);
    
    BLE::Instance().init(bleInitComplete);
}

// Reference
// http://files.amperka.ru/datasheets/nucleo-usermanual.pdf
// http://www.st.com/content/ccc/resource/technical/document/user_manual/65/e0/44/72/9e/34/41/8d/DM00026748.pdf/files/DM00026748.pdf/jcr:content/translations/en.DM00026748.pdf
// https://developer.mbed.org/users/mbed_official/code/mbed-dev/file/default/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PinNames.h
// https://developer.mbed.org/users/mbed_official/code/mbed-dev/file/default/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PeripheralPins.c
// http://www.st.com/content/ccc/resource/technical/document/datasheet/c5/ed/2f/60/aa/79/42/0b/DM00108832.pdf/files/DM00108832.pdf/jcr:content/translations/en.DM00108832.pdf
// http://www.st.com/en/microcontrollers/stm32l476rg.html
// http://jeelabs.org/book/1547a/index.html
// http://www.st.com/content/ccc/resource/technical/document/datasheet/33/d4/6f/1d/df/0b/4c/6d/CD00161566.pdf/files/CD00161566.pdf/jcr:content/translations/en.CD00161566.pdf