this is a new program based on BLE_Uart_Peripheral. Change program name due to relation Client&Peripheral to Client&Server

Dependencies:   RingBuffer nRF51_Vdd nRF51_WakeUp

This is a BLE Server (Device) program for nRF51.
You can communicate with mbed BLE using "BLE_Uart_Client" program as follows.
/users/kenjiArai/code/BLE_Uart_Client/
Please refer following my notebook.
/users/kenjiArai/notebook/ble-client-and-peripheral-using-switch-sience-ty51/#

Revision:
6:16e1f9d065a3
Parent:
5:394920d6a82f
Child:
7:0d94f4cf2a69
--- a/main.cpp	Mon Jun 13 09:54:32 2016 +0000
+++ b/main.cpp	Sun Oct 22 09:47:18 2017 +0000
@@ -15,7 +15,8 @@
  */
 
 /*
- *  ------- BLE Server UART function ------------------------------------------
+ *  ------- BLE Peripheral/Server UART function --------------------------------
+ *          communicate with BLE_UART_Client program
  *      --- Tested on Switch Science mbed TY51822r3 ---
  *
  *      http://www.page.sannet.ne.jp/kenjia/index.html
@@ -23,160 +24,126 @@
  *
  *      Started:  March     7th, 2016
  *      Revised:  June     13th, 2016
+ *      Revised:  October  22nd, 2017   Run on mbed-OS-5.6.2
  *
  *  Original program:
  *      BLE_LoopbackUART
- *      https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LoopbackUART/
+ *      https://developer.mbed.org/teams/Bluetooth-Low-Energy/
+ *                                  code/BLE_LoopbackUART/
  *  Tested Controller Device:
  *      BLE_Uart_Client
  *      https://developer.mbed.org/users/kenjiArai/code/BLE_Uart_Client/
- *
  */
 
-//  Include ---------------------------------------------------------------------------------------
+//  Include --------------------------------------------------------------------
 #include "mbed.h"
 #include "BLE.h"
 #include "UARTService.h"
 #include "nRF51_Vdd.h"
 #include "nRF51_WakeUp.h"
-#include "nRF51_lowpwr.h"
+#include "RingBuffer.h"
+
+//  Definition -----------------------------------------------------------------
+#define     NUM_ONCE            20
+#define     BFSIZE              (NUM_ONCE+4)
 
-//  Definition ------------------------------------------------------------------------------------
-//  Before using this function, please specify your program are used following functions or not.
-#define    USE_DEVICE_STDIO_MESSAGES       0   // printf
-#define    USE_DEVICE_SERIAL               1   // Serial or DEBUG & etc.
-#define    USE_DEVICE_I2C                  0   // Sensors with I2C, LCD, EEPROM, Driver chips & etc.
-#define    USE_DEVICE_SPI                  0   // Sensors with SPI, LCD, EEPROM, Driver chips & etc.
-#define    USE_DEVICE_SPISLAVE             0   // Communication with master vis SPI
-#define    USE_DEVICE_PWMOUT               0   // PWM duty output, Serve & etc.
-#define    USE_DEVICE_ANALOGIN             0   // Analog adc
-
-#define    GOTO_SLEEP_MODE                 0   // If you set 1, you need to connected LED1 and P0_0
-                                               // Please refer nRF51_WakeUP library
-
-#if USE_DEVICE_STDIO_MESSAGES
+// If you set 1, you need to connected LED1 and P_0
+// Please refer nRF51_WakeUP library
+#define     GOTO_SLEEP_MODE     0   
+                 
+//#define    USE_DEBUG_MODE
+#ifdef USE_DEBUG_MODE
 #define DEBUG(...) { printf(__VA_ARGS__); }
 #else
 #define DEBUG(...)
 #endif
 
-//  Object ----------------------------------------------------------------------------------------
+//  Object ---------------------------------------------------------------------
 BLE             ble;
 DigitalOut      connectedLED(LED2);
 InterruptIn     wake_up_sw(P0_1);
 nRF51_WakeUp    wakeup(LED1, P0_0);
 nRF51_Vdd       vdd(3.0f, 2.2f);
-Serial          pc(USBTX, USBRX);
+Serial          pc(USBTX, USBRX, 115200);
 UARTService     *uartServicePtr;
 Ticker          ticker;
+RingBuffer      ser_bf(1024);
+Thread          tsk;
+Mutex           bletx_mutex;
 
-//  ROM / Constant data ---------------------------------------------------------------------------
+//  ROM / Constant data --------------------------------------------------------
 #warning "You need to confirm your device name."
-const static char       DEVICE_NAME[] = "UART_S";
-const nRF51_LOWPWR_TypeDef  lowpwr_table = 
-                        {
-                        #if USE_DEVICE_STDIO_MESSAGES 
-                            true,
-                        #else
-                            false,
-                        #endif
-                        #if USE_DEVICE_SERIAL
-                            true,
-                        #else
-                            false,
-                        #endif
-                        #if USE_DEVICE_I2C
-                            true,
-                        #else
-                            false,
-                        #endif
-                        #if USE_DEVICE_SPI
-                            true,
-                        #else
-                            false,
-                        #endif
-                        #if USE_DEVICE_SPISLAVE
-                            true,
-                        #else
-                            false,
-                        #endif
-                        #if USE_DEVICE_PWMOUT
-                            true,
-                        #else
-                            false,
-                        #endif
-                        #if USE_DEVICE_ANALOGIN
-                            true
-                        #else
-                            false
-                        #endif
-                        };
+const static char DEVICE_NAME[] = "UART_S";
 
-//  RAM -------------------------------------------------------------------------------------------
-Gap::Address_t   my_mac;
-uint8_t          tx_buf[24];
-uint8_t          tx_len          = 0;
-uint8_t          rx_buf[24];
-uint8_t          rx_len          = 0;
-volatile bool    trigger_transmit   = false;
-volatile bool    trigger_receive    = false;
-volatile uint8_t command_continue   = 0;
-uint16_t         time_out_cntr   = 3600;
-volatile bool    time_out        = false;
-bool             line_input      = false;
-uint8_t          linebuf_irq[24];
-int              linebf_irq_len  = 0;
-uint8_t          linebuf[24];
-int              linebf_len      = 0;
-uint32_t         sleep_time      = 30;   // unit:second
+//  RAM ------------------------------------------------------------------------
+Gap::Address_t  my_mac;
+uint8_t         tx_buf[BFSIZE];
+uint8_t         tx_len                  = 0;
+uint8_t         rx_buf[BFSIZE];
+volatile bool   trigger_transmit        = false;
+volatile bool   trigger_receive         = false;
+volatile uint8_t command_continue       = 0;
+uint16_t        time_out_cntr           = 3600;
+volatile bool   time_out                = false;
+uint32_t        sleep_time              = 30;   // unit:second
+volatile bool   rx_isr_busy             = false;
 
-//  Function prototypes ---------------------------------------------------------------------------
+//  Function prototypes --------------------------------------------------------
 //      BLE
-void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params);
-void onDataWritten(const GattWriteCallbackParams *params);
-void periodicCallback(void);
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *);
+void onDataWritten_action(const GattWriteCallbackParams *);
+//      Tasks
+void pc_ser_rx(void);
+void data_from_ble(void);
+void Update_Values(void);
 //      Application related
-void adjust_line(uint8_t *bf);
+void command(uint8_t *cmd);
 void action_tx_help(void);
 void action_tx_vdd(void);
 void action_tx_temperature(void);
-void action_tx_wait_time(void);
-void fill_space_n(uint8_t *bf, uint8_t n);
-void Update_Values(void);
-int  xatoi (char **str, int32_t *res);
+void action_tx_wait_time(uint8_t *);
+void action_tx_quit(void);
+int  xatoi (char **, int32_t *);
+void adjust_line(uint8_t *);
 //      Interrupt related
-void action_tx_quit(void);
 void interrupt_by_sw(void);
 void serialRxCallback(void);
+void periodicCallback(void);
 
-//-------------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //  Control Program
-//-------------------------------------------------------------------------------------------------
-int main(void){
-    LowPwr set_lowpwr(&lowpwr_table);
+//------------------------------------------------------------------------------
+int main(void)
+{
     connectedLED = 0;
     pc.attach(&serialRxCallback, Serial::RxIrq);
     ticker.attach(periodicCallback, 1);
-    for (int k = 0; k < 20; k++) { pc.printf("\r\n");}          // clear terminal output
-    pc.printf("UART Communication / Server side\r\n");      // opening message
-    pc.printf("  Client(Central) and Server(Peripheral)\r\n");  // opening message
+    tsk.start(pc_ser_rx);
+    // clear terminal output
+    for (int k = 0; k < 5; k++) { pc.printf("\r\n");}
+    // opening message          
+    pc.printf("UART Communication / Server(Peripheral) side\r\n");
+    pc.printf("  need Client module (run BLE_Uart_Client program)\r\n");
     // Interrupt by switch
     wake_up_sw.fall(&interrupt_by_sw);
     ble.init();
     Gap::AddressType_t my_mac_type;
     ble.gap().getAddress(&my_mac_type, my_mac);
-    pc.printf(
+    DEBUG(
         "  my_MAC %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n",
         my_mac[5], my_mac[4], my_mac[3], my_mac[2], my_mac[1], my_mac[0],
         (my_mac_type == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random"
     );
     pc.printf(
-        "  mac_board_? = {0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x};\r\n",
+        "  mac_board_n = {0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x};\r\n",
         my_mac[0], my_mac[1], my_mac[2], my_mac[3], my_mac[4], my_mac[5]
     );
-    pc.printf("  Please write above mac_board_?(?=1,2,...) data into Client main.cpp\r\n");
+    pc.printf(
+        "  Please write above data(mac_board_n line) into mac_board_0\r\n");
+    pc.printf(
+        "    or follows(n=1,2,...)) in Client/main.cpp\r\n");
     ble.onDisconnection(disconnectionCallback);
-    ble.onDataWritten(onDataWritten);
+    ble.onDataWritten(onDataWritten_action);
     /* setup advertising */
     ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
     ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
@@ -205,38 +172,29 @@
             }
 #endif
         }
-        if (line_input){
-            line_input = false;
-            adjust_line(linebuf);
-            ble.updateCharacteristicValue(
-                uartServicePtr->getRXCharacteristicHandle(),
-                linebuf,
-                20
-            );
-        }
         if (trigger_transmit){
+            static uint8_t cmd_buf[BFSIZE];
+            static volatile bool   flag_continue = 0;
             trigger_transmit = false;
-            pc.printf("%s\r\n", rx_buf);
-            if ((rx_buf[0] == '*') || (rx_buf[0] == '&')){          
-                switch (rx_buf[1]){
-                    case 'v':
-                        action_tx_vdd();
-                        break;
-                    case 't':
-                        action_tx_temperature();
-                        break;
-                    case 'q':
-                        action_tx_quit();
-                        break;
-                    case 'w':
-                        action_tx_wait_time();
-                        break;
-                    case 'h':
-                    case '?':
-                        action_tx_help();
-                        break;
-                    default:
-                        break;
+            pc.printf((const char*)rx_buf);
+            if (flag_continue == true){
+                strcat((char *)cmd_buf, (char *)rx_buf);
+                if (strchr((const char*)cmd_buf,(int)'\r') == 0){
+                    flag_continue = true;
+                } else {
+                    command(cmd_buf);
+                    for(uint8_t i = 0; i < BFSIZE; i++){ cmd_buf[i] = 0;}
+                    flag_continue = false;
+                }
+            }
+            if ((rx_buf[0] == '~')){
+                strcpy((char *)cmd_buf, (char *)rx_buf);
+                if (strchr((const char*)cmd_buf,(int)'\r') == 0){
+                    flag_continue = true;
+                } else {
+                    command(cmd_buf);
+                    for(uint8_t i = 0; i < BFSIZE; i++){ cmd_buf[i] = 0;}
+                    flag_continue = false; 
                 }
             }
         }
@@ -244,109 +202,243 @@
     }
 }
 
-void serialRxCallback(){
-    char c = pc.getc();
-    if (c == '\r') {
-        linebuf_irq[linebf_irq_len++] = c;
-        pc.printf("\r\n");
-        linebf_len = linebf_irq_len;
-        strcpy((char *)linebuf, (char *)linebuf_irq);
-        linebf_irq_len = 0;
-        line_input = true;
-    } else if ((c == '\b') && linebf_irq_len) {
-        linebf_irq_len--;
-        pc.putc(c);
-        pc.putc(' ');
-        pc.putc(c);
-    } else if (((uint8_t)c >= ' ') && (linebf_irq_len < 20)) {
-        linebuf_irq[linebf_irq_len++] = c;
-        pc.putc(c);
-    } else if ( c == 0x1f ){    // Control+?
-        SCB->AIRCR = 0x05fa0004;    // System RESET!!
+void command(uint8_t *cmd)
+{
+    uint8_t *p = cmd;
+
+    while(*p == ' '){ ++p;}  // skip space
+    if (*p++ == '~'){
+        while(*p < '!'){ ++p;}  // skip space
+        uint8_t c = *p;
+        //pc.printf("c=%c\r\n", c);
+        switch (c){
+            case 'v':
+                action_tx_vdd();
+                break;
+            case 't':
+                action_tx_temperature();
+                break;
+            case 'q':
+                action_tx_quit();
+                break;
+            case 'w':
+                action_tx_wait_time(cmd);
+                break;
+            case 'h':
+            case '?':
+                action_tx_help();
+                break;
+            default:
+                //pc.printf("\r\nStep(%u)\r\n", __LINE__);
+                break;
+        }
     }
-    linebuf_irq[linebf_irq_len] = 0; 
+}
+
+void periodicCallback(void)
+{
+#if GOTO_SLEEP_MODE
+    if (--time_out_cntr == 0){
+        time_out = true;
+    }
+#endif
+    if (rx_isr_busy == true){
+        rx_isr_busy = false;
+    } else {
+        tsk.signal_set(0x01);
+    }
+}
+
+void serialRxCallback()
+{
+    ser_bf.save(pc.getc());
+    rx_isr_busy = true;
+    tsk.signal_set(0x01);
 }
 
-void adjust_line(uint8_t *bf){
+void pc_ser_rx()
+{
+    static uint8_t linebf_irq[BFSIZE];
+    static volatile uint8_t linebf_irq_len = 0;
+
+    while(true){
+        Thread::signal_wait(0x01);
+        if (ser_bf.check() == 0){
+            if (linebf_irq_len != 0){
+                linebf_irq[linebf_irq_len] = 0;
+                adjust_line(linebf_irq);
+                linebf_irq_len = 0;
+                bletx_mutex.lock();
+                ble.updateCharacteristicValue(
+                    uartServicePtr->getRXCharacteristicHandle(),
+                    linebf_irq,
+                    NUM_ONCE
+                );
+                bletx_mutex.unlock();
+            }
+        }
+        while(ser_bf.check() != 0){
+            char c = ser_bf.read();
+            if (c == '\b'){
+                linebf_irq_len--;
+                pc.putc(c);
+                pc.putc(' ');
+                pc.putc(c);
+            } else if ((c >= ' ') || (c == '\r') || (c == '\n')){
+                bool overflow = false;
+                if ((c == '\r') || (c == '\n')) {
+                    if (linebf_irq_len == NUM_ONCE - 1){// remain only 1 buffer
+                        overflow = true;
+                        linebf_irq[linebf_irq_len++] = '\r';
+                        pc.putc('\r');
+                    } else {
+                        overflow = false;
+                        linebf_irq[linebf_irq_len++] = '\r';
+                        linebf_irq[linebf_irq_len++] = '\n';
+                        pc.printf("\r\n");
+                    }
+                } else {
+                    linebf_irq[linebf_irq_len++] = c;
+                    pc.putc(c);
+                }
+                if (linebf_irq_len >= NUM_ONCE ){
+                    linebf_irq[linebf_irq_len] = 0;
+                    adjust_line(linebf_irq);
+                    linebf_irq_len = 0;
+                    bletx_mutex.lock();
+                    ble.updateCharacteristicValue(
+                        uartServicePtr->getRXCharacteristicHandle(),
+                        linebf_irq,
+                        NUM_ONCE
+                    );
+                    bletx_mutex.unlock();
+                    if (overflow == true){
+                        overflow = false;
+                        linebf_irq[linebf_irq_len++] = '\n';
+                        pc.putc('\n');
+                    }
+                }
+            }
+        }
+    }
+}
+
+void adjust_line(uint8_t *bf)
+{
     uint8_t i, c;
 
-    for (i = 0; i <20; bf++, i++){
+    for (i = 0; i <NUM_ONCE; bf++, i++){
         c = *bf;
-        if ( (c == '\r') || (c == '\n') || (c == 0)){
-            break;
-        }
+        if (c == 0){ break;}
     }
-    for (; i < 20; bf++, i++){
-        *bf = ' ';
-    }
+    for (; i < NUM_ONCE; bf++, i++){ *bf = 0x11;}
     *(bf + 1) = 0;
 }
 
-void onDataWritten(const GattWriteCallbackParams *params){
+void onDataWritten_action(const GattWriteCallbackParams *params)
+{
     if ((uartServicePtr != NULL) && 
         (params->handle == uartServicePtr->getTXCharacteristicHandle()))
     {
         strcpy((char *)rx_buf, (const char *)params->data);
-        rx_len = params->len;
         trigger_transmit = true;
-        DEBUG("RX_data\r\n");
-        DEBUG("Length: %d\r\n", rx_len);
-        DEBUG("Data: ");
-        DEBUG("%s", rx_buf);
-        DEBUG("\r\n");
     }
 }
 
-void action_tx_help(){
+void action_tx_help()
+{
                 //          12345678901234567890
-    sprintf((char *)tx_buf,"*? or &?:help");
+    sprintf((char *)tx_buf,"  ~?:help\r\n");
     tx_len = strlen((const char *)tx_buf); 
     Update_Values();
     wait(0.2);
                 //          12345678901234567890
-    sprintf((char *)tx_buf,"*v:vdd");
+    sprintf((char *)tx_buf,"  ~v:vdd\r\n");
     tx_len = strlen((const char *)tx_buf); 
     Update_Values();
     wait(0.2);
                 //          12345678901234567890
-    sprintf((char *)tx_buf,"*t:temperature");
+    sprintf((char *)tx_buf,"  ~t:temperature\r\n");
     tx_len = strlen((const char *)tx_buf); 
     Update_Values();
     wait(0.2);
                 //          12345678901234567890
-    sprintf((char *)tx_buf,"*w:wait time/ w 120");
+    sprintf((char *)tx_buf,"  ~w:wait, w 120\r\n");
     tx_len = strlen((const char *)tx_buf); 
     Update_Values();
     wait(0.2);
                 //          12345678901234567890
-    sprintf((char *)tx_buf,"*q:quit/sleep");
+    sprintf((char *)tx_buf,"  ~q:quit/sleep\r\n");
     tx_len = strlen((const char *)tx_buf); 
     Update_Values();
     wait(0.2);
 }
 
-void action_tx_vdd(){
-    sprintf((char *)tx_buf,"Vdd:%3.2fV", vdd.read_real_value());
+void action_tx_vdd()
+{
+    sprintf((char *)tx_buf,"Vdd: %3.2f V\r\n", vdd.read_real_value());
+    tx_len = strlen((const char *)tx_buf);
+    Update_Values();
+}
+
+void action_tx_temperature()
+{
+    int32_t p_temp;
+    float temperature;
+
+    // Update a temperature (inside nRF51822 chip)
+    sd_temp_get(&p_temp);
+    // -16.0f is offset vale for chip die temp
+    //         to ambient temp (depend on your board)
+    temperature = float(p_temp) / 4; // Original = float(p_temp)/4.0f - 16.0f;
+    sprintf((char *)tx_buf,"T: %+4.1f dC\r\n", temperature);
     tx_len = strlen((const char *)tx_buf);
     Update_Values();
 }
 
-void action_tx_temperature(){
-    int32_t p_temp;
-    float temperature;
- 
-    // Update a temperature (inside nRF51822 chip)
-    sd_temp_get(&p_temp);
-    // -16.0f is offset vale for chip die temp to ambient temp (depend on your board)
-    temperature = float(p_temp) / 4; // Original = float(p_temp)/4.0f - 16.0f;
-    sprintf((char *)tx_buf,"T:%+4.1fdC", temperature);
+void action_tx_wait_time(uint8_t *cmd)
+{
+    int32_t dt;
+    char *p;
+
+    p = (char *)(cmd);
+    p += 2; // point to time value
+    if (xatoi(&p, &dt)){
+        if (dt <= 5){ dt = 5;}
+        sleep_time = dt;    // set next wake-up period
+    } else {
+        DEBUG("data is unknown!\r\n");
+        sleep_time = 30;
+    }
+    DEBUG("slp_t:%d\r\n", sleep_time);
+    //pc.printf("slp_t:%d\r\n", sleep_time);
+                //          12345678901234567890
+    sprintf((char *)tx_buf, "W: %d sec\r\n", sleep_time);
     tx_len = strlen((const char *)tx_buf);
     Update_Values();
 }
 
+void action_tx_quit()
+{
+#if GOTO_SLEEP_MODE 
+    ticker.detach();
+                //          12345678901234567890
+    sprintf((char *)tx_buf,"Terminated the BLE");
+    tx_len = strlen((const char *)tx_buf); 
+    Update_Values();
+    wait(1.0);
+    wakeup.set_and_wait(sleep_time);
+    while(true){    // never come here but just in case
+        deepsleep();
+    }
+#else
+    SCB->AIRCR = 0x05fa0004;    // System RESET!!
+#endif
+}
 
 //  Change string -> integer
-int xatoi (char **str, int32_t *res){
+int xatoi (char **str, int32_t *res)
+{
     unsigned long val;
     unsigned char c, radix, s = 0;
 
@@ -413,68 +505,28 @@
     return 1;
 }
 
-void action_tx_wait_time(){
-    int32_t dt;
-    char *p;
-
-    p = (char *)(rx_buf);
-    p += 2; // point to rx_buf[2]
-    if (xatoi(&p, &dt)){
-        sleep_time = dt;    // set next wake-up period
-    } else {
-        DEBUG("data is unknown!\r\n");
-    }
-    DEBUG("slp_t:%d\r\n", sleep_time);
-                //          12345678901234567890
-    sprintf((char *)tx_buf, "W=%d", sleep_time);
-    tx_len = strlen((const char *)tx_buf);
-    Update_Values();
+void interrupt_by_sw() // Go to sleep
+{
+    NVIC_SystemReset();
+    // Not come here (Just in case)
+    sleep();
 }
 
-void action_tx_quit(){
-#if GOTO_SLEEP_MODE 
-    ticker.detach();
-                //          12345678901234567890
-    sprintf((char *)tx_buf,"Terminated the BLE");
-    tx_len = strlen((const char *)tx_buf); 
-    Update_Values();
-    wait(1.0);
-    wakeup.set_and_wait(sleep_time);
-    while(true){    // never come here but just in case
-        deepsleep();
-    }
-#else
-    SCB->AIRCR = 0x05fa0004;    // System RESET!!
-#endif
-}
-
-void interrupt_by_sw(){         // Go to sleep
-    NVIC_SystemReset();
-    // Not come here (Just in case)
-    deepsleep();
-}
-
-void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
+{
     DEBUG("Disconnected!\r\n");
     DEBUG("Restarting the advertising process\r\n");
     ble.startAdvertising();
 }
 
-void periodicCallback(void){
-#if GOTO_SLEEP_MODE
-    if (--time_out_cntr == 0){
-        time_out = true;
-    }
-#endif
-}
-
-void Update_Values(void){
+void Update_Values(void)
+{
+    bletx_mutex.lock();
     ble.updateCharacteristicValue(
         uartServicePtr->getRXCharacteristicHandle(),
         tx_buf,
         tx_len
     );
-    DEBUG("TX_data: %s\r\n", tx_buf);
-    DEBUG("Length: %d\r\n", tx_len);
+    bletx_mutex.unlock();
     tx_len = 0;
 }