This is a modified "BLE_Default_App". It doesn't use retargetStdout() which allows it to work with online Libs available on 20150123 (nRF51822, BLE_API)

Dependencies:   BLE_API mbed nRF51822

App for FOTA testing:

  • IO:
    • Blinks a LED on platform to show App alive
    • LEDs also follow buttons to show immediate response.
    • BLE UART has ping message, and also echos back any received bytes (Use with Android App: nRF UART 2.0).
  • It compiles and runs as FOTA and non-FOTA platform which may assist debugging
    • platform "Nordic nRF51822 FOTA" for FOTA Loading
    • platform "Nordic nRF51822" for mbed drive loading
  • Supports mbed and non-mbed PCBs (all compiled using platform "Nordic nRF51822 FOTA")
  • Compile options available for:
    • nRF51822-mkit (Includes USB Serial Debug)
    • nRF51822-EK
    • nRF51822-Beacon (nRFBeacon)
    • Atomwear (Button and LED on main PCB only)
    • *If anyone gets this working with other publicly available PCBs let me know and we can add it in

main.cpp

Committer:
prussell
Date:
2015-02-20
Revision:
6:85f68f27170c
Parent:
5:ac98ff227ad7

File content as of revision 6:85f68f27170c:

//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 drive (Hex File >250KB)

/* mbed Microcontroller Library
 * Copyright (c) 2006-2015 Paul Russell
 *
 * 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  // nRF51822-mkit   
#define D_EK        2  // nRF51822-EK 
#define D_BEACON    3  // nRF51822-Beacon 
#define D_ATOMWEAR  4  // Atomwear  

//==============================
// Compile Options:
#define D_BLE_UART  1  // Include BLE UART functionality?
#define D_PING_SEC  1  // Ping Rate in Seconds

#define D_PCB    D_MKIT         // Select target PCB
//#define D_MkitPROBING 1         // Option: Drive pwm on select header signals to aid probing with scope, comment out this line to disable
//#define D_PCB    D_EK           // Select target PCB
//#define D_PCB    D_BEACON       // Select target PCB
//#define D_PCB    D_ATOMWEAR     // Select target PCB
//#define D_AtomPROBING   1     // Option: Drive pwm on select Debug Header signals to support probing with scope (PWM 10%~80%), comment out this line to disable **Disconnect all modules except Main/Debug/Battery**

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

//============================== Process PCB Options:
#if D_PCB==D_MKIT
    const char *pcDeviceName = "FOTA4r6m";
    const char *pcPingBLE  = "m4\n";            // May need "\n" to push BLE Tx
    const char *pcPingUART = "u4\n";

    #define DEBUG(...) { printf(__VA_ARGS__); } //UART: p0.08~p0.11, Debug OK over USB Serial
    DigitalIn       bB1in(BUTTON1);             //p0.16 =Button1
    DigitalIn       bB2in(BUTTON2);             //p0.17 =Button2
    InterruptIn     B1int(BUTTON1);             //p0.16 =Button1
    InterruptIn     B2int(BUTTON2);             //p0.17 =Button2
    DigitalOut      bL1out(LED1);               //p0.18 =LED1
    DigitalOut      bL2out(LED2);               //p0.19 =LED2
    //PwmOut fL1pwm(LED1); float fL1level = 0.1;//p0.18 =LED1, BrightnessFloat(0.0~1.0)
    //PwmOut fL2pwm(LED2); float fL2level = 0.1;//p0.19 =LED2, BrightnessFloat(0.0~1.0)
    //AnalogIn      adcA(p1);                   //p0.01 =AIN2
    //AnalogIn      adcB(p2);                   //p0.02 =AIN3

    #define D_0_LED_TICKER    { bL1out=((uTicker1++)&0x01);}    // LED Follows Ticker (May also follow a button)
    #define D_1_LED_BUTTON    { bL1out = !bB1in;}               // LED Follows !Button
    #define D_2_LED_BUTTON    { bL2out = !bB2in;}               // LED Follows !Button
    #define D_OPERATION_LED   "mkit: LED1=Ticker+Button1, LED2=Button2"
 
#elif D_PCB==D_EK
    const char *pcDeviceName = "FOTA4r6e";
    const char *pcPingBLE  = "e4\n";            // May need "\n" to push BLE Tx

    #define DEBUG(...) {}                       //Serial Debug not connected 
    DigitalIn       bB1in(BUTTON1);             //p0.16 =Button0
    DigitalIn       bB2in(BUTTON2);             //p0.17 =Button1
    InterruptIn     B1int(BUTTON1);             //p0.16 =Button0
    InterruptIn     B2int(BUTTON2);             //p0.17 =Button1
    DigitalOut      bL1out(LED1);               //p0.18 =LED0
    DigitalOut      bL2out(LED2);               //p0.19 =LED1
    //PwmOut fL1pwm(LED1); float fL1level = 0.1;//p0.18 =LED0, BrightnessFloat(0.0~1.0)
    //PwmOut fL2pwm(LED2); float fL2level = 0.1;//p0.19 =LED1, BrightnessFloat(0.0~1.0)
    //AnalogIn      adcA(p1);                   //p0.01 =AIN2
    //AnalogIn      adcB(p2);                   //p0.02 =AIN3
  
    #define D_0_LED_TICKER    { bL1out=((uTicker1++)&0x01);}    // LED Follows Ticker (May also follow a button)
    #define D_1_LED_BUTTON    { bL1out = !bB1in;}               // LED Follows !Button
    #define D_2_LED_BUTTON    { bL2out = !bB2in;}               // LED Follows !Button
    #define D_OPERATION_LED   "EK: LED0=Ticker+Button0, LED1=Button1"

 #elif D_PCB==D_BEACON
    const char *pcDeviceName = "FOTA4r6b";
    const char *pcPingBLE  = "b4\n";            // May need "\n" to push BLE Tx
 
    #define DEBUG(...) {}                       //Serial Debug not connected 
    DigitalIn       bB1in(p8);                  //p0.08 =SW1
    DigitalIn       bB2in(p18);                 //p0.18 =SW2
    InterruptIn     B1int(p8);                  //p0.08 =SW1
    InterruptIn     B2int(p18);                 //p0.18 =SW2
    DigitalOut      bLRout(p16);                //p0.16 =LEDR
    DigitalOut      bLGout(p12);                //p0.12 =LEDG
    DigitalOut      bLBout(p15);                //p0.15 =LEDB
    //PwmOut fLRpwm(p16); float fLRlevel = 0.1; //p0.16 =LEDR, BrightnessFloat(0.0~1.0)
    //PwmOut fLGpwm(p12); float fLGlevel = 0.1; //p0.12 =LEDG, BrightnessFloat(0.0~1.0)
    //PwmOut fLBpwm(p15); float fLBlevel = 0.1; //p0.15 =LEDB, BrightnessFloat(0.0~1.0)
    //AnalogIn      adcA(p1);                   //p0.01 =AIN2
    //AnalogIn      adcB(p2);                   //p0.02 =AIN3

    #define D_0_LED_TICKER    { bLRout=((uTicker1++)&0x01);}    // LED Follows Ticker (May also follow a button)
    #define D_1_LED_BUTTON    { bLGout = bB1in;}                // LED Follows Button
    #define D_2_LED_BUTTON    { bLBout = bB2in;}                // LED Follows Button
    #define D_OPERATION_LED   "Beacon: Red=Ticker, Green=SW1, Blue=SW2"
  
#elif D_PCB==D_ATOMWEAR     //  USBSerial=None, ButtonLED=atomwear, LEDx=Buttonx, LEDw=Buttony|Ticker
    const char *pcDeviceName = "FOTA4r6a";
    const char *pcPingBLE  = "a\n";            // May need "\n" to push BLE Tx
 
    #define DEBUG(...) {}                       //Serial Debug not connected 
    DigitalIn       bB1in(p29);                 //p0.29 =S1
    InterruptIn     B1int(p29);                 //p0.29 =S1
    DigitalOut      bLBout(p17);                //p0.17 =LEDB
    DigitalOut      bLWout(p18);                //p0.18 =LEDW
    //PwmOut fLBpwm(p17); float fLBlevel = 0.1; //p0.17 =LEDB, BrightnessFloat(0.0~1.0)
    //PwmOut fLWpwm(p18); float fLWlevel = 0.1; //p0.18 =LEDW, BrightnessFloat(0.0~1.0)
    //AnalogIn      adcA(p1);                   //p0.01 =AIN2
    //AnalogIn      adcB(p2);                   //p0.02 =AIN3
  
    #define D_0_LED_TICKER    { bLBout=((uTicker1++)&0x01);}    // LED Follows Ticker (May also follow a button)
    #define D_1_LED_BUTTON    { bLWout = bB1in;}                // LED Follows Button
    #define D_OPERATION_LED   "Atomwear: Blue=Ticker, White=S1"

#else
    #error Unknown PCB
#endif

//============================== BLE
BLEDevice ble;
#if D_BLE_UART==1
    #include "UARTService.h"
    UARTService *uartServicePtr;
    #define D_OPERATION_BLE     ", BLE-UART=[Echo typing, and ping on Ticker]\n"
#else
    #define D_OPERATION_BLE     ", BLE-UART not enabled\n"
#endif

#include "DeviceInformationService.h"
//? #include "DFUService.h"   //Required if "DFUService dfu(ble)" is explicitely declared

//============================== Handle Button Activity
void onButton(void)
{   // Handle any button changes
    DEBUG("B\n");

    D_1_LED_BUTTON; // Update LED from Button
#ifdef D_2_LED_BUTTON
    D_2_LED_BUTTON; // Update LED from Button
#endif
};

//============================== Handle Ticker1
uint8_t uTicker1;
void onTicker1(void) 
{
    DEBUG(pcPingUART);
    D_0_LED_TICKER; // Update LED from Ticker

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

//============================== 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
    ble.startAdvertising(); // restart advertising //20150130: Thanks to Wayne Keenan (waynek) for spotting this missing line!!
}

void onDataWritten(const GattCharacteristicWriteCBParams *params)
{
#if D_BLE_UART==1
    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);
    }
#else
        DEBUG("Unexpected Characteristic Write, Handle:%d\n", params->charHandle);
#endif
}

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

    DEBUG("BLE Init %s\n", pcDeviceName);
    DEBUG("After FOTA loading any unused IO pins may hold previous state, initialize all pins or reset to clear\n");
    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");
    DeviceInformationService deviceInfo(ble, "ARM", pcDeviceName, "SN1000", "hw-rev1", "fw-rev1");

    //Enable FOTA DFU
//?    DFUService dfu(ble); // Included implicitely by ble.init() for FOTA platforms, but doing explicitly may be desired for some cases

#if D_BLE_UART==1
    UARTService uartService(ble);   //Setup BLE UART
    uartServicePtr = &uartService;
#endif

    DEBUG(D_OPERATION_LED D_OPERATION_BLE);
    B1int.fall(&onButton); B1int.rise(&onButton); // Button1
#ifdef D_2_LED_BUTTON
    B2int.fall(&onButton); B2int.rise(&onButton); // Button2
#endif

#if D_PCB==D_MKIT
  #ifdef D_MkitPROBING
    //**Warning:As of 20150219 nRF appears to have max 3 PwmOut channels, others don't output but compile OK. (Maybe see SoftPWM or FastPWM for more channels)

    //For IO Pinout check: PWM 10%~80% on Debug Header pins to allow probing verification:
    // Signals by schematic (User guide has typos), arranged by header rows from PCB edge
    //     nRF51                 PWM  //mkit    
    PwmOut pwm_p30(p30); pwm_p30=0.1; //P6.7
  #endif
#endif

#if D_PCB==D_ATOMWEAR
  #ifdef D_AtomPROBING
    //**Disconnect all modules except Main/Debug/Battery**

    //**Warning:As of 20150219 nRF appears to have max 3 PwmOut channels, others don't output but compile OK. (Maybe see SoftPWM or FastPWM for more channels)

    //For IO Pinout check: PWM 10%~80% on Debug Header pins to allow probing verification:
    // Signals by schematic (User guide has typos), arranged by header rows from PCB edge
    //     nRF51                 PWM // Schematic //Header Bus //Silkscreen     
    PwmOut pwm_p13(p13); pwm_p13=0.1;// SPI_SCK1  //P17.2  22  //8
    PwmOut pwm_p14(p14); pwm_p14=0.2;// SPI_MOSI1 //P17.4  23  //10
    PwmOut pwm_p15(p15); pwm_p15=0.3;// SPI_MISO1 //P17.6  24  //12

//    PwmOut pwm_p0(p0);   pwm_p0=0.4;// GPIO1     //P17.1  11  //7
//    PwmOut pwm_p2(p2);   pwm_p2=0.5;// GPIO2     //P17.3  10  //9
//    PwmOut pwm_p3(p3);   pwm_p3=0.6;// GPIO3     //P17.5  9   //11

//    PwmOut pwm_p12(p12); pwm_p12=0.7;// UART_RX   //P15.2  21  //2
//    PwmOut pwm_p11(p11); pwm_p11=0.8;// UART_TX   //P15.4  20  //4 
    //     ----         // VCC Unreg //P15.6  13  //6    ==Unregulated Power from Battery (Regulator on nRF PCB)

    //     SWDIO        // SWDIO     //P15.1  19  //1
    //     SWCLK        // SWDCLK    //P15.3  18  //3
    //     GND          // GND       //P15.5  15  //5
  #endif
#endif


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