1st release version. Set TYBLE16 as Central mode

Dependencies:   mbed

Fork of TYBLE16_BME280_data_sender by Kenji Arai

Please refer following page.
/users/kenjiArai/notebook/tyble16-module--uart-communication-between-central/#

main.cpp

Committer:
kenjiArai
Date:
2017-11-19
Revision:
2:17fdd6d3877f
Parent:
1:f2982d4f4037

File content as of revision 2:17fdd6d3877f:

/*
 * Mbed Application program / Using Akizuki BLE Module AE-TYBLE16
 *      on-board module : TAIYO YUDEN BLE 4.2 TYSA-B (EYSGJNAWY-WX)
 *
 *  http://akizukidenshi.com/catalog/g/gK-12339/
 *
 *  Refernce document
 *  https://www.yuden.co.jp/wireless_module/document/datareport2/jp/
 *                  TY_BLE_EYSGJNAWY_WX_BriefDataReport_V1_3_20170925J.pdf
 *
 * Copyright (c) 2017 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created:    October   27th, 2017
 *      Revised:    November  19th, 2017
 */

/*
    Tested condition
        mbed-os-5.6.4 & mbed Rev.157(release 155)
    Nucleo-F446RE   TYBLE16 /also F411RE
        PA_9 (D8)    pin5  / P0.03(UART_RX)
        PA_10(D2)    pin6  / P0.01(UART_TX)
                     pin7  / P0.02(UART_CTS) connected to pin8 / P0.00(UART_RTS)
        +3.3v        pin14 / +V
        GND          pin13 / GND
 */

/*
  --- HOW TO SET "CENTRAL(CLIENT) MODE" ---
    TYBLE16 default setting is "Peripheral(Server) Mode"
    If you want to use it as "Central mode", you need to proceed follows
    1) You run this program on a Mbed board connected with TYBLE16 module
    2) Just after running the program, you can identify the mode "Central" or
       "Peripheral" in your terminal screen
    3) If your module is "Peripheral", please enter 'c' for switching the mode
    4) Power off the module then restart again and check the mode
    5) Please use
       "TYBLE16_UART_Central_and_Peripheral" program as sample application
 */

//  Include --------------------------------------------------------------------
#include "mbed.h"

//  Definition -----------------------------------------------------------------
enum operating_mode_t {
    MODE_UNKNOWN            = -1,   // Unknown Error
    MODE_CENTRAL            =  0,   // Central
    MODE_PERIPHERAL         =  1,   // Peripheral
};

//  Object/ Constructor --------------------------------------------------------
Serial      pc(USBTX,USBRX);
Serial      tyble16(D8, D2);    // Choose proper pin assignment in your Mbed
Ticker      t;

//  RAM ------------------------------------------------------------------------
uint8_t timeout_readable;
operating_mode_t my_role;
uint8_t cmd[8];

//  ROM / Constant data --------------------------------------------------------
char *const msg =
    "Set TYBLE16 Central or Peripheral, created on UTC: "__TIME__","__DATE__"";
char *const err_msg =
    "Cannot detect BLE! Please check the hardware!\r\n";
char *const ble_msg = "-- From BLE(followed line) --";
char *const cmd_force_reset = "BRS\r\n";
char *const cmd_advert_stop = "BCD0\r\n";
char *const cmd_change_to_c = "BRL1\r\n";
char *const cmd_change_to_p = "BRL0\r\n";

//  Function prototypes --------------------------------------------------------
void set_central_mode(void);
void one_sec(void);
void get_line (char *, int);
void stop_broadcasting(char *);
char *get_ble_message(char *);
void command_preparation(void);

//------------------------------------------------------------------------------
//  Control Program
//------------------------------------------------------------------------------
int main()
{
    command_preparation();
    pc.printf("\r\n\r\n%s\r\n", msg); 
    t.attach(&one_sec, 1.0f);
    while(true){
        set_central_mode();
    }
}

// Every 1 second
void one_sec(void){               // execute every 1second
    if( timeout_readable){        --timeout_readable; }
}

// Peripheral mode (Default setting) change to Central mode
void set_central_mode(void)
{
    static char linebuf[64];
    static char blebuf[64];
    char *ptr;
    char c;

    // Reset BLE
    pc.printf("Start from BLE reset\r\n");
    {   // need to keep this order (does not divide each other)
        tyble16.puts(cmd_force_reset);
        pc.printf("force to reset\r\n%s%s\r\n",
                ble_msg, get_ble_message(blebuf));
    }
    if (strstr(blebuf , "Ver.") != NULL){
        ;
    } else {
        pc.printf(err_msg);
        while(true){;}
    }  
    wait_ms(10);
    // Stop current action
    {   // need to keep this order (does not divide each other)
        tyble16.puts(cmd_advert_stop);
        get_ble_message(blebuf);
    }
    if (strstr(blebuf , "ACK") != NULL){
        my_role = MODE_PERIPHERAL;
    } else if (strstr(blebuf , "NAK") != NULL){
        {   // need to keep this order (does not divide each other)
            tyble16.printf("%s", cmd);
            get_ble_message(blebuf);
        }
        if (strstr(blebuf , "ACK") != NULL){
            my_role = MODE_CENTRAL;
        } else {
            pc.printf(err_msg);
            while(true){;}
        }
    } else {
        pc.printf(err_msg);
        while(true){;}
    }
    pc.printf("Current mode: ");
    if (my_role == MODE_CENTRAL){
        pc.printf("Central\r\n");
    } else if (my_role == MODE_PERIPHERAL){
        pc.printf("Peripheral\r\n");
    } else {
        pc.printf("unknown\r\n");
    }
    c = linebuf[0];
    stop_broadcasting(blebuf);
    pc.printf("Define Central or Peripheral\r\n");
    pc.printf("Central -> c, Peripheral -> p, ");
    pc.printf("Keep current setting -> any key\r\n");
    pc.printf("Please enter c or p\r\n=");
    ptr = linebuf;
    get_line(ptr, sizeof(linebuf));
    pc.putc('\r');
    c = linebuf[0];
    if ((c == 'c') || (c == 'C')){
        pc.printf(cmd_change_to_c);
        {   // need to keep this order (does not divide each other)
            tyble16.printf(cmd_change_to_c);
            pc.printf("Switch to Central\r\n%s%s\r\n",
                    ble_msg, get_ble_message(blebuf));
        }
        if (strstr(blebuf , "ACK") != NULL){     // check ACK words
            my_role = MODE_CENTRAL;
            pc.printf("BST5010000\r\n");
            {// need to keep this order (does not divide each other)
                tyble16.printf("BST5010000\r\n");
                pc.printf("Set PSKEY value\r\n");
                pc.printf("Checking paired signal forever\r\n");
            }
            pc.printf("Changed to Central mode\r\nPlease power-off");
            pc.printf(" then Peripheral will active!\r\n");
        } else if (strstr(blebuf , "NAK") != NULL){
            if (my_role == MODE_PERIPHERAL){
                pc.printf("Stay in Periphral mode\r\n");
            } else {
                pc.printf("Stay in Central mode\r\n");
            }
        } else {
            pc.printf("??\r\n");
        }
    } else if ((c == 'p') || (c == 'P')){
        pc.printf(cmd_change_to_p);
        {   // need to keep this order (does not divide each other)
            tyble16.printf(cmd_change_to_p);
            pc.printf("Switch to Peripheral\r\n%s%s\r\n",
                    ble_msg, get_ble_message(blebuf));
        }
        if (strstr(blebuf , "ACK") != NULL){     // check ACK words
            my_role = MODE_PERIPHERAL;
            pc.printf("BST501003C\r\n");
            {// need to keep this order (does not divide each other)
                tyble16.printf("BST501003C\r\n"); // default data 60 sec
                pc.printf("Set PSKEY value\r\n");
                pc.printf("Advertising 60sec timeout\r\n");
            }
            pc.printf("Changed to Periphral mode\r\nPlease power-off");
            pc.printf(" then Peripheral will active!\r\n");
        } else if (strstr(blebuf , "NAK") != NULL){
            if (my_role == MODE_PERIPHERAL){
                pc.printf("Stay in Periphral mode\r\n");
            } else {
                pc.printf("Stay in Central mode\r\n");
            }
        } else {
            pc.printf("??\r\n");
        }
    } else {
        pc.printf("Keep current setting\r\n");
    }
    pc.printf("Hit any key to go again!\r\n");
    while(pc.getc() == 0){;}
}

void stop_broadcasting(char *buf)
{
    // Stop Advertising or Scanning (just in case)
    if (my_role == MODE_PERIPHERAL){
        pc.printf("Stop Advertising\r\n");
        tyble16.puts(cmd_advert_stop);
    } else {
        pc.printf("Stop Central action\r\n");
        tyble16.printf("%s", cmd);
    }
    // need to keep this order (does not divide puts & get_ble_message)
    pc.printf("%s%s\r\n", ble_msg, get_ble_message(buf));
    if (buf[2] == 'A'){
        if (buf[3] ==  'C'){
            if (buf[4] ==  'K'){
                return;
            }
        }
    }
    if (my_role == MODE_PERIPHERAL){
        pc.printf("Try again,Stop Central action\r\n");
        tyble16.printf("%s", cmd);
    } else {
        pc.printf("Try again,Stop Advertising\r\n");
        tyble16.puts(cmd_advert_stop);   // try Peripheral
    }
    // need to keep this order (does not divide puts & get_ble_message)
    pc.printf("n%s%s\r\n", ble_msg, get_ble_message(buf));
    if (buf[2] == 'A'){
        if (buf[3] ==  'C'){
            if (buf[4] ==  'K'){
                // change role C to P or P to C
                if (my_role == MODE_PERIPHERAL){
                    my_role = MODE_CENTRAL;
                    pc.printf("Mode changes to Central\r\n");
                } else {
                    my_role = MODE_PERIPHERAL;
                    pc.printf("Mode changes to Peripheral\r\n");
                }
                return;
            }
        }
    }
}

char *get_ble_message(char *buf)
{
    char c;

    uint8_t cr_cnt = 0;
    uint16_t i = 0;
    timeout_readable = 5u;  // 5sec
    while (true){
        c = tyble16.getc();
        buf[i++] = c;
        if (c == '\n'){
            ++cr_cnt;
        }
        if ((cr_cnt == 2u) || (timeout_readable == 0)){
            buf[i] = 0;
            break;
        }
    }
    return buf;
}

//  Get key input data
void get_line (char *buff, int len)
{
    char c;
    int idx = 0;

    for (;;) {
        c = pc.getc();
        if (c == '\r') {
            buff[idx++] = c;
            break;
        }
        if ((c == '\b') && idx) {
            idx--;
            pc.putc(c);
            pc.putc(' ');
            pc.putc(c);
        }
        if (((uint8_t)c >= ' ') && (idx < len - 1)) {
            buff[idx++] = c;
            pc.putc(c);
        }
    }
    buff[idx++] = '\r';     // <CR>
    buff[idx++] = '\n';     // <LF>
    buff[idx] = 0;
    pc.putc('\n');
}

// You do not need to understand & just execute
void command_preparation(void)
{
    char *const cmd_abc    = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
    char cmd_abc_order[10] = {1,18,2,0x80,26,27,0xff,0xff,0xff,0xff};

    char *p = cmd_abc;
    for(uint32_t i = 0; i < 8;i++){
        char c = cmd_abc_order[i];
        if(c == 0x80){cmd[i] = '0';} else
        if(c == 0xff){cmd[i] = 0;} else
                     {cmd[i] = *(p + c);}
    }
}