Default_Castum_AppFOTA4_Working

Dependencies:   mbed BLE_API nRF51822

main.cpp

Committer:
prussell
Date:
2015-01-26
Revision:
3:3651f1a58d9e
Parent:
2:0931d94f42a2
Child:
4:3a065a4e3ca6

File content as of revision 3:3651f1a58d9e:

//To load over FOTA set platform to "Nordic nRF51822 FOTA" and use DFU feature of App "nRF Master Control Panel" (Hex file <100K)
//To use normal mbed loading set platform to "Nordic nRF51822" and copy to mbed virtual disk (Hex File >250KB)

/* 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.
 */

//==============================
// Build Options for D_PCB
#define D_MKIT   1              // mkit: USBSerial=OK,   ButtonLED=m, LED2=Button2, LED1=Button1|Ticker   
#define D_EK     2              // mkit: USBSerial=None, ButtonLED=m, LED1=Button1, LED0=Button0|Ticker 
#define D_BEACON 3              // mkit: USBSerial=None, ButtonLED=b, LEDx=Buttonx, LEDy=Buttony|Ticker 

//==============================
// Compile Options:
#define D_PING_SEC     1        // Ping Rate in Seconds
#define D_PCB    D_MKIT         // Define the PCB to compile for
//#define D_PCB    D_EK           // Define the PCB to compile for
//#define D_PCB    D_BEACON       // Define the PCB to compile for

//==============================
#include "mbed.h"
#include "BLEDevice.h"

#include "DFUService.h"
#include "UARTService.h"
#include "DeviceInformationService.h"

//============================== Process PCB Options:
#if D_PCB==D_MKIT
    const char *pcDeviceName = "FOTA4.3.m";
    const char *pcPingBLE  = "m4\n";    // Need "\n" for BLE to Tx (and possibly so as not to block FOTA DFU).
    const char *pcPingUART = "u4\n";
    #define D_ALTBUTTONLED  0   // Use Default
    #define D_USBDEBUG      1   // Use USB Serial
#elif D_PCB==D_EK
    const char *pcDeviceName = "FOTA4.3.e";
    const char *pcPingBLE  = "e4\n";    // Need "\n" for BLE to Tx (and possibly so as not to block FOTA DFU).
    #define D_ALTBUTTONLED  0   // Use Default
    #define D_USBDEBUG      0   // No USB Serial
#elif D_PCB==D_BEACON
    const char *pcDeviceName = "FOTA4.3.b";
    const char *pcPingBLE  = "b4\n";    // Need "\n" for BLE to Tx (and possibly so as not to block FOTA DFU).
    #define D_ALTBUTTONLED  1   // Use Alternate
    #define D_USBDEBUG      0   // No USB Serial
#else
    #error Unknown PCB
#endif

//============================== Debug: BLE vs USBSerial
#if D_USBDEBUG
    #define DEBUG(...) { printf(__VA_ARGS__); } // Debug OK over BLE and USB 
#else 
    //#define DEBUG(...) { if(!ble.getGapState().connected){ printf(__VA_ARGS__); } } // Debug Only if BLE Connected *20150123: Not Available: uartService.retargetStdout()
    #define DEBUG(...) /* nothing */
    //TODO: sprintf and output length limited string over BLE without using uartService.retargetStdout()?
 #endif /* #if D_USBDEBUG */

//============================== IO
BLEDevice ble;
UARTService *uartServicePtr;

#if D_ALTBUTTONLED //nRFBeacon
#define D_LED_LO 1      // LEDs Active Lo
#define D_BUTTON_LO 1   // Buttons Active Lo
//UART: p0.08~p0.11 // Careful of mkit UART output clashing
DigitalIn       bB1in(p8);     //nRF51822p0.08 SW1 == Clashes with USBSerial
DigitalIn       bB2in(p18);    //nRF51822p0.18 SW2
InterruptIn     B1int(p8);     //nRF51822p0.08 //B1int.rise(&onB1rise);   == Clashes with USBSerial
InterruptIn     B2int(p18);    //nRF51822p0.18 //B1int.fall(&onB1fall);
DigitalOut      bL1out(p16);   // Direct LEDR drive
DigitalOut      bL2out(p12);   // Direct LEDG drive
//DigitalOut      bL2out(p15);   // Direct LEDB drive
//PwmOut          fL0pwm(p16); float fL0level = 0.1;  // PWM LED1, brightness=float(0.0~1.0)
//PwmOut          fL1pwm(p12); float fL1level = 0.1;  // PWM LED2, brightness=float(0.0~1.0)
//PwmOut          fL2pwm(p15); float fL2level = 0.1;  // PWM LED2, brightness=float(0.0~1.0)
//AnalogIn      adcA(p1); // nRF51822p0.01==pin05==AIN2
//AnalogIn      adcB(p2); // nRF51822p0.02==pin06==AIN3
#else  //mkit,ek (Note in EK actually LED0/1 Button0/1)
#define D_LED_LO 0      // LEDs Active Hi
#define D_BUTTON_LO 1   // Buttons Active Lo
//UART: p0.08~p0.11
DigitalIn       bB1in(BUTTON1); //nRF51822p0.16 //if(bB1in){} /
DigitalIn       bB2in(BUTTON2); //nRF51822p0.17 //if(bB2in){}
InterruptIn     B1int(BUTTON1); //nRF51822p0.16 //B1int.rise(&onB1rise);  
InterruptIn     B2int(BUTTON2); //nRF51822p0.17 //B1int.fall(&onB1fall);
DigitalOut      bL1out(LED1);   // Direct LED1 drive
DigitalOut      bL2out(LED2);   // Direct LED2 drive
//PwmOut          fL1pwm(LED1); float fL1level = 0.1;  // PWM LED1, brightness=float(0.0~1.0)
//PwmOut          fL2pwm(LED2); float fL2level = 0.1;  // PWM LED2, brightness=float(0.0~1.0)
//AnalogIn      adcA(p1); // nRF51822p0.01==pin05==AIN2
//AnalogIn      adcB(p2); // nRF51822p0.02==pin06==AIN3
#endif // Beacon or mkit/EK

//============================== Handle Button Activity
void onButton(void)
{   // Handle any button changes
    DEBUG("B\n");
    //DEBUG("Button Activity!\n");
#if D_LED_LO //Active Lo
    bL1out=bB1in;    //Direct LED1=Button1 (Press=LED On), *Will be overridden on next Tick
    bL2out=bB2in;    //Direct LED2=Button2 (Press=LED On)
#else //LEDs Active Hi
    bL1out=!bB1in;   //Direct LED1=Button1 (Press=LED On), *Will be overridden on next Tick
    bL2out=!bB2in;   //Direct LED2=Button2 (Press=LED On)
#endif

};

//============================== Handle Ticker1
uint8_t uTicker1;
void onTicker1(void) 
{
    DEBUG(pcPingUART);
    bL1out=((uTicker1++)&0x01);    // Blink L1/Lgreen at Ticker Rate

    if (uartServicePtr != NULL) { 
        ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (const uint8_t *)pcPingBLE, strlen(pcPingBLE)); // BLE UART = Ping Message (Max 20char)
    }
}

//============================== Handle BLE: Disconnect, Written...
void onDisconnect(Gap::Handle_t tHandle, Gap::DisconnectionReason_t eReason)
{
    // When BLE Disconnected mkit may output over long DEBUG over USB Serial (Careful of IO clash on other PCBs)
    DEBUG("\nBLEi: Callback_BLE_Disconnect(Handle:%d, eReason:0x%02x=", tHandle, eReason );//PR: Occurs properly when click disconnect in App nRFToolbox:HRM
    switch(eReason) {
        case Gap::REMOTE_USER_TERMINATED_CONNECTION: DEBUG("REMOTE_USER_TERMINATED_CONNECTION"); break;
        case Gap::CONN_INTERVAL_UNACCEPTABLE:        DEBUG("CONN_INTERVAL_UNACCEPTABLE"); break;
        case Gap::LOCAL_HOST_TERMINATED_CONNECTION:  DEBUG("LOCAL_HOST_TERMINATED_CONNECTION"); break;
        default:                                     DEBUG("UNKNOWN"); break;
    }
    DEBUG("), Restarting Advertising\n", tHandle, eReason );//PR: Occurs properly when click disconnect in App nRFToolbox:HRM
}

void onDataWritten(const GattCharacteristicWriteCBParams *params)
{
    if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) {
        uint16_t bytesRead = params->len;
        DEBUG("BLE-UART Echo Rx[%u]=[%*s]\n", bytesRead, params->len, params->data);
        ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead);
    } else {
        DEBUG("Unexpected Characteristic Write, Handle:%d\n", params->charHandle);
    }
}

//==============================
int main(void)
{
    Ticker ticker1;
    ticker1.attach(onTicker1, D_PING_SEC); //Ping Rate

    DEBUG("BLE Init %s\n", pcDeviceName);
    ble.init();
    ble.onDisconnection(onDisconnect);
    ble.onDataWritten(onDataWritten);

    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)pcDeviceName, strlen(pcDeviceName));

    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); /* needs to be connectable to allow use of DFUService */
    //ble.setAdvertisingInterval(1600); /* 1s; in multiples of 0.625ms. */
    ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000));    //PR: Advertise 1sec (1Hz)
    ble.startAdvertising();

    DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1000", "hw-rev1", "fw-rev1");

    /* Enable over-the-air firmware updates. Instantiating DFUSservice introduces a
     * control characteristic which can be used to trigger the application to
     * handover control to a resident bootloader. */
    DFUService dfu(ble);

    /* Setup a BLE service for console output. Redirect stdout to BLE-UART(When connected). */
    UARTService uartService(ble);
    uartServicePtr = &uartService;
    //uartService.retargetStdout(); // This isn't working with online libs BLE_API and nRF51822 updated 2015Jan23

    DEBUG("mkit: LED2=[Follow Button2], LED1=[Blink on Ticker, and Follow Button1], BLE-UART=[Echo typing, and ping on Ticker]\n");
    B1int.fall(&onButton);   // Button1 Press/fall
    B1int.rise(&onButton);   // Button1 Release/rise
    B2int.fall(&onButton);   // Button2 Press/fall
    B2int.rise(&onButton);   // Button2 Release/rise

    for (;;) {
        ble.waitForEvent();
   }
}
//========== end: main.cpp ==========