mbed OS V5 BLE UARTService to USB/UART PassThru Example

Moxon Design : mbed OS V5 BLE UartService to USBUART passthru example

This example will advertise on BLE as "BLART" and allow BLE serial echo to the USB Serial port. Open a Bluetooth terminal application, like Nordic "nRF UART" and connect to "BLART", open a terminal emulator program, like "TeraTERM", and connect to the USB COM Port (like JLink CDC UART Port), and echo characters back and forth. Set UART_LoopBack = 1 for local loopback (e.g. BLE to BLE, USB-UART to USB-UART)

main.cpp

Committer:
moxondesign
Date:
2017-04-29
Revision:
2:3e203cc2a88f
Parent:
1:5b50f5283781

File content as of revision 2:3e203cc2a88f:

/* mbed BLE Library - USB/UART Serial Pass-thru Example
 *
 * author    : Moxon Design
 * date      : 4/27/2017
 * platforms : Rigado BLE-350/300, Nordic rRF52-DK, rRF51-DK
 * requires  : mBed Platform Version 5+
 
 * Overview: 
 * 
 * Employs the mBed platform ble/services/UARTService for UART emulation,
 * as well as exposing the phyical UART device connected to the USB host,
 * providing a transparent bridge between the two interfaces. By default, 
 * Serial dev(USBTX, USBRX);
 *
 * Set "UART_LoopBack" to enable local loopback test instead of pass-thru.
 * 
 * Notes : 
 * 1) Advertises as "BLART" for BLe-usbUART
 * 2) ble/services/UARTService is 20 byte max packets or about 4800 Baud (be patient)
 * 3) transparent bridge
 *
 * License :
 *
 * 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.
 */
 
/* mbed platform defines */
#include "mbed.h"
#include "ble/BLE.h"
#include "ble/services/UARTService.h"

/* got debug? */
/* Set this if you need debug messages on the console */
/* Negative impact on code-size and power consumption */
#define DEBUG_OUTPUT 0 
#if DEBUG_OUTPUT
#define DEBUG(...) { printf(__VA_ARGS__); }
#else
#define DEBUG(...) /* no output mapped */
#endif

/* instantiate BLE services and softUART service */
BLEDevice  ble;
UARTService *uartServicePtr;
int UART_LoopBack = 0;
 
/* instantiate hardware UART devices                */
/* devicename(TXD, RXD);                            */
/* for "JLink CDC UART Port" use the define below : */
/* Serial dev(USBTX, USBRX);                      */
/* otherwise use the hardware UART on 0.12 & 0.11   */
/* (a.k.a. d1 & D1 in Arduino parlance...           */
 //Serial dev(P0_12, P0_11);
 Serial dev(USBTX, USBRX);
 static uint8_t rx_buf[32];
 static uint8_t rx_len=0;
 int tx_buf;
 static uint8_t tx_len=0;

/* define some blinky LED fun */
DigitalOut led1(LED1);
//DigitalOut led2(LED2);
//DigitalOut led3(LED3);
//DigitalOut led4(LED4);

void theBLEdisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    #if DEBUG_OUTPUT
      DEBUG("Disconnected!\n\r");
      DEBUG("Restarting the advertising process\n\r");
    #endif
    ble.startAdvertising();
}

void theBLEonDataWritten(const GattWriteCallbackParams *params)
{
    if ((uartServicePtr != NULL) && (params->handle == uartServicePtr->getTXCharacteristicHandle())) {
        uint16_t bytesRead = params->len;
        uint8_t byteCnt;
        
        #if DEBUG_OUTPUT
          DEBUG("BLART BLE received %u bytes\n\r", bytesRead);
        #endif
        
        if (UART_LoopBack == 0) {
          /* pass thru BLE UART data to UART1 */
          for (byteCnt = 0; byteCnt < bytesRead; byteCnt++) {
              dev.putc(params->data[byteCnt]);
          } 
        } else {
          /* otherwise, loopback BLE UART data to itself */    
          ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead);
        }
    }
}

void theUARTonDataWritten(void) {
    while(dev.readable())    
    {
        rx_buf[rx_len++] = dev.getc();
        #if DEBUG_OUTPUT
          DEBUG("BLART BLE received %u \n\r", rx_buf[rx_len]);
        #endif    
             if (UART_LoopBack == 0) {
              ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), rx_buf, rx_len);
              rx_len = 0;
            } else {
                for (tx_len = 0; tx_len < rx_len; tx_len++) {
                  tx_buf = rx_buf[tx_len];  
                  dev.putc(tx_buf);
                }
                rx_len = 0;
            } 
    }            
}

void theTickCallback(void)
{
    /* toggle the LED each timer tick (1 sec) */
    led1 = !led1;
}

int main(void)
{
    /* set up a 1 sec timer to toggle the LED */ 
    led1 = 1;
    Ticker ticker;
    ticker.attach(theTickCallback, 1);

    /* attach the hardwate UART1 data received callback */
    dev.attach( &theUARTonDataWritten , dev.RxIrq);
    
    /* initialze the BLE services */
    #if DEBUG_OUTPUT
      DEBUG("Initialising the nRF5x\n\r");
    #endif
    ble.init();
    ble.onDisconnection(theBLEdisconnectionCallback);
    ble.onDataWritten(theBLEonDataWritten);

    /* setup the BLE advertising */
    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    /* my names "BLART", what's yours? */
     #if DEBUG_OUTPUT
      DEBUG("Advertising nRF5x as BLART i.e. BLe-uART\n\r");
    #endif  
    ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
                                     (const uint8_t *)"BLART", sizeof("BLART") - 1);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                     (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));

    /* Advertising Rate at 1000ms, a multiple of the 0.625ms base timer */
    ble.setAdvertisingInterval(1000); 
    ble.startAdvertising();

    /* start the BLE UARTServices */
    UARTService uartService(ble);
    uartServicePtr = &uartService;

    /* start the hardware UART1 */
    //uart1.printf("Hello! My name is BLART, what's yours?\n");
    
    /* main loop */
    while (true) {
        /* call wait to give other threads a chance to run */
        ble.waitForEvent();
    }
}