Kenji Arai / TYBLE16_mbedlized_os5_several_examples

Dependencies:   BME280 TextLCD nRF51_Vdd

Fork of TYBLE16_mbedlized_os5_BASE by Kenji Arai

Files at this revision

API Documentation at this revision

Comitter:
kenjiArai
Date:
Sat Apr 14 04:56:34 2018 +0000
Parent:
0:6eea047171a3
Child:
2:47ad8c48224e
Commit message:
added samples

Changed in this revision

0_Blinky_LED/main.cpp Show annotated file Show diff for this revision Revisions of this file
1_Check_RTC/main.cpp Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/Eddystone/EddystoneService.cpp Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/Eddystone/EddystoneService.h Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/Eddystone/EddystoneTypes.h Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/Eddystone/TLMFrame.cpp Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/Eddystone/TLMFrame.h Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/Eddystone/UIDFrame.cpp Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/Eddystone/UIDFrame.h Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/Eddystone/URLFrame.cpp Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/Eddystone/URLFrame.h Show annotated file Show diff for this revision Revisions of this file
2_EddyStoneBeacon/main.cpp Show annotated file Show diff for this revision Revisions of this file
3_Heart_Rate/main.cpp Show annotated file Show diff for this revision Revisions of this file
4_RCBController/RCBController.h Show annotated file Show diff for this revision Revisions of this file
4_RCBController/main.cpp Show annotated file Show diff for this revision Revisions of this file
5_SDCard/FatFs_Mon/mon.cpp Show annotated file Show diff for this revision Revisions of this file
5_SDCard/FatFs_Mon/mon.h Show annotated file Show diff for this revision Revisions of this file
5_SDCard/main.cpp Show annotated file Show diff for this revision Revisions of this file
5_SDCard/sd-driver.lib Show annotated file Show diff for this revision Revisions of this file
6_Thermo/main.cpp Show annotated file Show diff for this revision Revisions of this file
7_Uart_Client/main.cpp Show annotated file Show diff for this revision Revisions of this file
7_Uart_Client/original.cpp Show annotated file Show diff for this revision Revisions of this file
8_Uart_Server/main.cpp Show annotated file Show diff for this revision Revisions of this file
9_Monitor/debug_tools/debug_common.h Show annotated file Show diff for this revision Revisions of this file
9_Monitor/debug_tools/debug_nRF5x.cpp Show annotated file Show diff for this revision Revisions of this file
9_Monitor/debug_tools/debugging_nRF5x.h Show annotated file Show diff for this revision Revisions of this file
9_Monitor/debug_tools/mon_hw_common.h Show annotated file Show diff for this revision Revisions of this file
9_Monitor/debug_tools/mon_hw_config.h Show annotated file Show diff for this revision Revisions of this file
9_Monitor/debug_tools/mon_hw_mem.h Show annotated file Show diff for this revision Revisions of this file
9_Monitor/debug_tools/mon_hw_nRF5x.cpp Show annotated file Show diff for this revision Revisions of this file
9_Monitor/main.cpp Show annotated file Show diff for this revision Revisions of this file
TYBLE16_os5_BASE.lib Show annotated file Show diff for this revision Revisions of this file
common/BME280.lib Show annotated file Show diff for this revision Revisions of this file
common/TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
common/nRF51_Vdd.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show diff for this revision Revisions of this file
select_example.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/0_Blinky_LED/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,50 @@
+/*
+ * Mbed Application program / Blinky
+ *
+ * Copyright (c) 2018 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    April     10th, 2018
+ *      Revised:    April     14th, 2018
+ */
+
+//#define EXAMPLE_0_BLINKY_LED
+#ifdef EXAMPLE_0_BLINKY_LED
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "TYBLE16_BASE.h"
+
+//  Definition -----------------------------------------------------------------
+
+//  Constructor ----------------------------------------------------------------
+DigitalOut  my_led(LED1);
+Serial      pc(USBTX, USBRX);
+
+//  RAM ------------------------------------------------------------------------
+
+//  ROM / Constant data --------------------------------------------------------
+char *const opngmsg =
+    "\x1b[2J\x1b[H"__FILE__ "\r\n"__DATE__ " " __TIME__ " (UTC)\r\n""\r\n";
+
+//  Function prototypes --------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+int main()
+{
+    uint32_t count = 0;
+
+    pc.puts(opngmsg);
+    // Check TYBLE-16 configuration
+    cpu_sys();
+    compile_condition();
+    while(true) {
+        my_led = !my_led;
+        pc.printf("%8u\r\n", count++);
+        Thread::wait(1000);
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/1_Check_RTC/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,237 @@
+/*
+ * Mbed Application program / check RTC (Real Time Clock)
+ *
+ * Copyright (c) 2017,'18 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    August    11th, 2017
+ *      Revised:    April     14th, 2018
+ */
+
+//#define EXAMPLE_1_CHECK_RTC
+#ifdef EXAMPLE_1_CHECK_RTC
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "TYBLE16_BASE.h"
+
+//  Definition -----------------------------------------------------------------
+
+//  Constructor ----------------------------------------------------------------
+DigitalIn   userSW(BUTTON1);
+DigitalOut  myled(LED1);         // Indicate the sampling period
+Serial      pc(USBTX, USBRX);
+
+//  RAM ------------------------------------------------------------------------
+
+//  ROM / Constant data --------------------------------------------------------
+char *const msg0  = "Is a time correct? If no, please hit any key. ";
+char *const msg1  = "<Push USER SW then enter sleep mode> ";
+char *const msg2  = "\r\nEnter Standby Mode, please push RESET to wake-up\r\n";
+char *const opngmsg =
+    "\x1b[2J\x1b[H"__FILE__ "\r\n"__DATE__ " " __TIME__ " (UTC)\r\n""\r\n";
+
+//  Function prototypes --------------------------------------------------------
+static void time_enter_mode(void);
+static void chk_and_set_time(char *ptr);
+static void goto_standby(void);
+static int  xatoi (char **str, unsigned long *res);
+static void get_line (char *buff, int len);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+int main()
+{
+    char buf[64];               // data buffer for text
+    time_t seconds;
+    uint8_t wait_counter = 0;
+
+    pc.puts(opngmsg);
+    // Check TYBLE-16 configuration
+    cpu_sys();
+    compile_condition();
+    myled = !myled;
+    wait(1.0);
+    myled = !myled;
+    wait(1.0);
+    while(1) {
+        seconds = time(NULL);
+        strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
+        pc.printf("[Time] %s", buf);
+        pc.printf(msg0);
+        pc.printf("%s\r", msg1);
+        wait_counter = 0;
+        while (seconds == time(NULL)) {
+            if (pc.readable() == 1) {
+                buf[0] = pc.getc();  // dummy read
+                time_enter_mode();
+            }
+            if (userSW == 0) {
+                pc.printf(msg2);
+                wait(1.0);
+                myled = 0;
+                goto_standby();
+            }
+            wait(0.05);
+            if (++wait_counter > (2000 / 50)) {
+                break;
+            }
+        }
+        uint8_t n = strlen(msg0) + strlen(msg1);
+        for (uint8_t i = 0; i < n; i++) {
+            pc.putc(' ');
+        }
+        pc.printf("      \r"); // Not use '\n'
+        myled = !myled;
+    }
+}
+
+void time_enter_mode(void)
+{
+    char *ptr;
+    char linebuf[64];
+
+    pc.printf("\r\nSet time into RTC\r\n");
+    pc.printf(" e.g. >18 4 14 10 11 12 -> April 14th,'18, 10:11:12\r\n");
+    pc.printf(" If time is fine, just hit enter\r\n");
+    pc.putc('>');
+    ptr = linebuf;
+    get_line(ptr, sizeof(linebuf));
+    pc.printf("\r");
+    chk_and_set_time(ptr);
+}
+
+void goto_standby(void)
+{
+    deepsleep();   // Not Standby Mode but Deep Sleep Mode
+}
+
+//  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] = 0;
+    pc.putc('\n');
+}
+
+void chk_and_set_time(char *ptr)
+{
+    unsigned long p1;
+    struct tm t;
+    time_t seconds;
+
+    if (xatoi(&ptr, &p1)) {
+        t.tm_year       = (uint8_t)p1 + 100;
+        pc.printf("Year:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mon        = (uint8_t)p1 - 1;
+        pc.printf("Month:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mday       = (uint8_t)p1;
+        pc.printf("Day:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_hour       = (uint8_t)p1;
+        pc.printf("Hour:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_min        = (uint8_t)p1;
+        pc.printf("Min:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_sec        = (uint8_t)p1;
+        pc.printf("Sec: %d \r\n",p1);
+    } else {
+        return;
+    }
+    seconds = mktime(&t);
+    set_time(seconds);
+    pc.printf(
+        "Date: %04d/%02d/%02d, %02d:%02d:%02d\r\n",
+        t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec
+    );
+}
+
+//  Change string -> integer
+int xatoi (char **str, unsigned long *res)
+{
+    unsigned long val;
+    unsigned char c, radix, s = 0;
+
+    while ((c = **str) == ' ') {
+        (*str)++;
+    }
+    if (c == '-') {
+        s = 1;
+        c = *(++(*str));
+    }
+    if (c == '0') {
+        c = *(++(*str));
+        if (c <= ' ') {
+            *res = 0;
+            return 1;
+        }
+        if (c == 'x') {
+            radix = 16;
+            c = *(++(*str));
+        } else {
+            if (c == 'b') {
+                radix = 2;
+                c = *(++(*str));
+            } else {
+                if ((c >= '0')&&(c <= '9')) {
+                    radix = 8;
+                } else {
+                    return 0;
+                }
+            }
+        }
+    } else {
+        if ((c < '1')||(c > '9')) {
+            return 0;
+        }
+        radix = 10;
+    }
+    val = 0;
+    while (c > ' ') {
+        if (c >= 'a') {
+            c -= 0x20;
+        }
+        c -= '0';
+        if (c >= 17) {
+            c -= 7;
+            if (c <= 9) {
+                return 0;
+            }
+        }
+        if (c >= radix) {
+            return 0;
+        }
+        val = val * radix + c;
+        c = *(++(*str));
+    }
+    if (s) {
+        val = -val;
+    }
+    *res = val;
+    return 1;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/Eddystone/EddystoneService.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,570 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+
+#include "EddystoneService.h"
+
+/* Initialise the EddystoneService using parameters from persistent storage */
+EddystoneService::EddystoneService(BLE                 &bleIn,
+                                   EddystoneParams_t   &paramsIn,
+                                   const PowerLevels_t &advPowerLevelsIn,
+                                   const PowerLevels_t &radioPowerLevelsIn,
+                                   uint32_t            advConfigIntervalIn) :
+    ble(bleIn),
+    operationMode(EDDYSTONE_MODE_NONE),
+    urlFrame(paramsIn.urlData, paramsIn.urlDataLength),
+    uidFrame(paramsIn.uidNamespaceID, paramsIn.uidInstanceID),
+    tlmFrame(paramsIn.tlmVersion),
+    resetFlag(false),
+    tlmBatteryVoltageCallback(NULL),
+    tlmBeaconTemperatureCallback(NULL)
+{
+    lockState         = paramsIn.lockState;
+    flags             = paramsIn.flags;
+    txPowerMode       = paramsIn.txPowerMode;
+    beaconPeriod      = correctAdvertisementPeriod(paramsIn.beaconPeriod);
+
+    memcpy(lock,             paramsIn.lock,      sizeof(Lock_t));
+    memcpy(unlock,           paramsIn.unlock,    sizeof(Lock_t));
+
+    eddystoneConstructorHelper(advPowerLevelsIn, radioPowerLevelsIn, advConfigIntervalIn);
+}
+
+/* When using this constructor we need to call setURLData,
+ * setTMLData and setUIDData to initialise values manually
+ */
+EddystoneService::EddystoneService(BLE                 &bleIn,
+                                   const PowerLevels_t &advPowerLevelsIn,
+                                   const PowerLevels_t &radioPowerLevelsIn,
+                                   uint32_t            advConfigIntervalIn) :
+    ble(bleIn),
+    operationMode(EDDYSTONE_MODE_NONE),
+    urlFrame(),
+    uidFrame(),
+    tlmFrame(),
+    lockState(false),
+    resetFlag(false),
+    lock(),
+    unlock(),
+    flags(0),
+    txPowerMode(0),
+    beaconPeriod(DEFAULT_BEACON_PERIOD_MSEC),
+    tlmBatteryVoltageCallback(NULL),
+    tlmBeaconTemperatureCallback(NULL)
+{
+    eddystoneConstructorHelper(advPowerLevelsIn, radioPowerLevelsIn, advConfigIntervalIn);
+}
+
+/* Setup callback to update BatteryVoltage in TLM frame */
+void EddystoneService::onTLMBatteryVoltageUpdate(TlmUpdateCallback_t tlmBatteryVoltageCallbackIn)
+{
+    tlmBatteryVoltageCallback = tlmBatteryVoltageCallbackIn;
+}
+
+/* Setup callback to update BeaconTemperature in TLM frame */
+void EddystoneService::onTLMBeaconTemperatureUpdate(TlmUpdateCallback_t tlmBeaconTemperatureCallbackIn)
+{
+    tlmBeaconTemperatureCallback = tlmBeaconTemperatureCallbackIn;
+}
+
+void EddystoneService::setTLMData(uint8_t tlmVersionIn)
+{
+   tlmFrame.setTLMData(tlmVersionIn);
+}
+
+void EddystoneService::setURLData(const char *urlDataIn)
+{
+    urlFrame.setURLData(urlDataIn);
+}
+
+void EddystoneService::setUIDData(const UIDNamespaceID_t *uidNamespaceIDIn, const UIDInstanceID_t *uidInstanceIDIn)
+{
+    uidFrame.setUIDData(uidNamespaceIDIn, uidInstanceIDIn);
+}
+
+EddystoneService::EddystoneError_t EddystoneService::startConfigService(void)
+{
+    if (operationMode == EDDYSTONE_MODE_CONFIG) {
+        /* Nothing to do, we are already in config mode */
+        return EDDYSTONE_ERROR_NONE;
+    } else if (advConfigInterval == 0) {
+        /* Nothing to do, the advertisement interval is 0 */
+        return EDDYSTONE_ERROR_INVALID_ADVERTISING_INTERVAL;
+    }
+
+    if (operationMode == EDDYSTONE_MODE_BEACON) {
+        ble.shutdown();
+        /* Free unused memory */
+        freeBeaconFrames();
+        operationMode = EDDYSTONE_MODE_CONFIG;
+        ble.init(this, &EddystoneService::bleInitComplete);
+        return EDDYSTONE_ERROR_NONE;
+    }
+
+    operationMode = EDDYSTONE_MODE_CONFIG;
+    setupConfigService();
+    return EDDYSTONE_ERROR_NONE;
+}
+
+EddystoneService::EddystoneError_t EddystoneService::startBeaconService(uint16_t consecUrlFramesIn, uint16_t consecUidFramesIn, uint16_t consecTlmFramesIn)
+{
+    if (operationMode == EDDYSTONE_MODE_BEACON) {
+        /* Nothing to do, we are already in beacon mode */
+        return EDDYSTONE_ERROR_NONE;
+    } else if (!consecUrlFramesIn && !consecUidFramesIn && !consecTlmFramesIn) {
+        /* Nothing to do, the user wants 0 consecutive frames of everything */
+        return EDDYSTONE_ERROR_INVALID_CONSEC_FRAMES;
+    } else if (!beaconPeriod) {
+        /* Nothing to do, the period is 0 for all frames */
+        return EDDYSTONE_ERROR_INVALID_BEACON_PERIOD;
+    }
+
+    /* Setup tracking of the current advertised frame. Note that this will
+     * cause URL or UID frames to be advertised first!
+     */
+    currentAdvertisedFrame            = EDDYSTONE_FRAME_TLM;
+    consecFrames[EDDYSTONE_FRAME_URL] = consecUrlFramesIn;
+    consecFrames[EDDYSTONE_FRAME_UID] = consecUidFramesIn;
+    consecFrames[EDDYSTONE_FRAME_TLM] = consecTlmFramesIn;
+
+    memset(currentConsecFrames, 0, sizeof(uint16_t) * NUM_EDDYSTONE_FRAMES);
+
+    if (operationMode == EDDYSTONE_MODE_CONFIG) {
+        ble.shutdown();
+        /* Free unused memory */
+        freeConfigCharacteristics();
+        operationMode = EDDYSTONE_MODE_BEACON;
+        ble.init(this, &EddystoneService::bleInitComplete);
+        return EDDYSTONE_ERROR_NONE;
+    }
+
+    operationMode = EDDYSTONE_MODE_BEACON;
+    setupBeaconService();
+    return EDDYSTONE_ERROR_NONE;
+}
+
+/* It is not the responsibility of the Eddystone implementation to store
+ * the configured parameters in persistent storage since this is
+ * platform-specific. So we provide this function that returns the
+ * configured values that need to be stored and the main application
+ * takes care of storing them.
+ */
+void EddystoneService::getEddystoneParams(EddystoneParams_t *params)
+{
+    params->lockState     = lockState;
+    params->flags         = flags;
+    params->txPowerMode   = txPowerMode;
+    params->beaconPeriod  = beaconPeriod;
+    params->tlmVersion    = tlmFrame.getTLMVersion();
+    params->urlDataLength = urlFrame.getEncodedURLDataLength();
+
+    memcpy(params->advPowerLevels, advPowerLevels,               sizeof(PowerLevels_t));
+    memcpy(params->lock,           lock,                         sizeof(Lock_t));
+    memcpy(params->unlock,         unlock,                       sizeof(Lock_t));
+    memcpy(params->urlData,        urlFrame.getEncodedURLData(), urlFrame.getEncodedURLDataLength());
+    memcpy(params->uidNamespaceID, uidFrame.getUIDNamespaceID(), sizeof(UIDNamespaceID_t));
+    memcpy(params->uidInstanceID,  uidFrame.getUIDInstanceID(),  sizeof(UIDInstanceID_t));
+}
+
+/* Helper function used only once during constructing the object to avoid
+ * duplicated code.
+ */
+void EddystoneService::eddystoneConstructorHelper(const PowerLevels_t &advPowerLevelsIn,
+                                                  const PowerLevels_t &radioPowerLevelsIn,
+                                                  uint32_t            advConfigIntervalIn)
+{
+    advConfigInterval = (advConfigIntervalIn > 0) ? correctAdvertisementPeriod(advConfigIntervalIn) : 0;
+
+    memcpy(radioPowerLevels, radioPowerLevelsIn, sizeof(PowerLevels_t));
+    memcpy(advPowerLevels,   advPowerLevelsIn,   sizeof(PowerLevels_t));
+
+    /* TODO: Note that this timer is started from the time EddystoneService
+     * is initialised and NOT from when the device is booted. So app needs
+     * to take care that EddystoneService is one of the first things to be
+     * started!
+     */
+    timeSinceBootTimer.start();
+}
+
+/* When changing modes, we shutdown and init the BLE instance, so
+ * this is needed to complete the initialisation task.
+ */
+void EddystoneService::bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext)
+{
+    if (initContext->error != BLE_ERROR_NONE) {
+        /* Initialisation failed */
+        return;
+    }
+
+    switch (operationMode) {
+    case EDDYSTONE_MODE_CONFIG:
+        setupConfigService();
+        break;
+    case EDDYSTONE_MODE_BEACON:
+        setupBeaconService();
+        break;
+    default:
+        /* Some error occurred */
+        break;
+    }
+}
+
+void EddystoneService::swapAdvertisedFrame(void)
+{
+    /* This essentially works out which is the next frame to be swapped in
+     * and updated the advertised packets. It will eventually terminate
+     * and in the worst case the frame swapped in is the current advertised
+     * frame.
+     */
+    while (true) {
+        currentAdvertisedFrame = (currentAdvertisedFrame + 1) % NUM_EDDYSTONE_FRAMES;
+
+        if (currentAdvertisedFrame == EDDYSTONE_FRAME_URL && consecFrames[EDDYSTONE_FRAME_URL] > 0) {
+            updateAdvertisementPacket(rawUrlFrame, urlFrame.getRawFrameSize());
+            return;
+        } else if (currentAdvertisedFrame == EDDYSTONE_FRAME_UID && consecFrames[EDDYSTONE_FRAME_UID] > 0) {
+            updateAdvertisementPacket(rawUidFrame, uidFrame.getRawFrameSize());
+            return;
+        } else if (currentAdvertisedFrame == EDDYSTONE_FRAME_TLM && consecFrames[EDDYSTONE_FRAME_UID] > 0) {
+            updateRawTLMFrame();
+            updateAdvertisementPacket(rawTlmFrame, tlmFrame.getRawFrameSize());
+            return;
+        }
+    }
+}
+
+/* Helper function that calls user-defined functions to update Battery Voltage and Temperature (if available),
+ * then updates the raw frame data and finally updates the actual advertised packet. This operation must be
+ * done fairly often because the TLM frame TimeSinceBoot must have a 0.1 secs resolution according to the
+ * Eddystone specification.
+ */
+void EddystoneService::updateRawTLMFrame(void)
+{
+    if (tlmBeaconTemperatureCallback != NULL) {
+        tlmFrame.updateBeaconTemperature((*tlmBeaconTemperatureCallback)(tlmFrame.getBeaconTemperature()));
+    }
+    if (tlmBatteryVoltageCallback != NULL) {
+        tlmFrame.updateBatteryVoltage((*tlmBatteryVoltageCallback)(tlmFrame.getBatteryVoltage()));
+    }
+    tlmFrame.updateTimeSinceBoot(timeSinceBootTimer.read_ms());
+    tlmFrame.constructTLMFrame(rawTlmFrame);
+}
+
+void EddystoneService::updateAdvertisementPacket(const uint8_t* rawFrame, size_t rawFrameLength)
+{
+    ble.gap().clearAdvertisingPayload();
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, EDDYSTONE_UUID, sizeof(EDDYSTONE_UUID));
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, rawFrame, rawFrameLength);
+}
+
+void EddystoneService::setupBeaconService(void)
+{
+    /* Initialise arrays to hold constructed raw frames */
+    if (consecFrames[EDDYSTONE_FRAME_URL] > 0) {
+        rawUrlFrame = new uint8_t[urlFrame.getRawFrameSize()];
+        urlFrame.constructURLFrame(rawUrlFrame, advPowerLevels[txPowerMode]);
+    }
+
+    if (consecFrames[EDDYSTONE_FRAME_UID] > 0) {
+        rawUidFrame = new uint8_t[uidFrame.getRawFrameSize()];
+        uidFrame.constructUIDFrame(rawUidFrame, advPowerLevels[txPowerMode]);
+    }
+
+    if (consecFrames[EDDYSTONE_FRAME_TLM] > 0) {
+        rawTlmFrame = new uint8_t[tlmFrame.getRawFrameSize()];
+        /* Do not initialise because we have to reconstruct every 0.1 secs */
+    }
+
+    /* Configure advertisements */
+    ble.gap().setTxPower(radioPowerLevels[txPowerMode]);
+    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
+    ble.gap().setAdvertisingInterval(beaconPeriod);
+    ble.gap().onRadioNotification(this, &EddystoneService::radioNotificationCallback);
+    ble.gap().initRadioNotification();
+
+    /* Set advertisement packet payload */
+    swapAdvertisedFrame();
+
+    /* Start advertising */
+    ble.gap().startAdvertising();
+}
+
+void EddystoneService::setupConfigService(void)
+{
+    lockStateChar      = new ReadOnlyGattCharacteristic<bool>(UUID_LOCK_STATE_CHAR, &lockState);
+    lockChar           = new WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(Lock_t)>(UUID_LOCK_CHAR, lock);
+    unlockChar         = new WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(Lock_t)>(UUID_UNLOCK_CHAR, unlock);
+    urlDataChar        = new GattCharacteristic(UUID_URL_DATA_CHAR, urlFrame.getEncodedURLData(), 0, URL_DATA_MAX, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
+    flagsChar          = new ReadWriteGattCharacteristic<uint8_t>(UUID_FLAGS_CHAR, &flags);
+    advPowerLevelsChar = new ReadWriteArrayGattCharacteristic<int8_t, sizeof(PowerLevels_t)>(UUID_ADV_POWER_LEVELS_CHAR, advPowerLevels);
+    txPowerModeChar    = new ReadWriteGattCharacteristic<uint8_t>(UUID_TX_POWER_MODE_CHAR, &txPowerMode);
+    beaconPeriodChar   = new ReadWriteGattCharacteristic<uint16_t>(UUID_BEACON_PERIOD_CHAR, &beaconPeriod);
+    resetChar          = new WriteOnlyGattCharacteristic<bool>(UUID_RESET_CHAR, &resetFlag);
+
+    lockChar->setWriteAuthorizationCallback(this, &EddystoneService::lockAuthorizationCallback);
+    unlockChar->setWriteAuthorizationCallback(this, &EddystoneService::unlockAuthorizationCallback);
+    urlDataChar->setWriteAuthorizationCallback(this, &EddystoneService::urlDataWriteAuthorizationCallback);
+    flagsChar->setWriteAuthorizationCallback(this, &EddystoneService::basicAuthorizationCallback<uint8_t>);
+    advPowerLevelsChar->setWriteAuthorizationCallback(this, &EddystoneService::basicAuthorizationCallback<PowerLevels_t>);
+    txPowerModeChar->setWriteAuthorizationCallback(this, &EddystoneService::powerModeAuthorizationCallback);
+    beaconPeriodChar->setWriteAuthorizationCallback(this, &EddystoneService::basicAuthorizationCallback<uint16_t>);
+    resetChar->setWriteAuthorizationCallback(this, &EddystoneService::basicAuthorizationCallback<bool>);
+
+    charTable[0] = lockStateChar;
+    charTable[1] = lockChar;
+    charTable[2] = unlockChar;
+    charTable[3] = urlDataChar;
+    charTable[4] = flagsChar;
+    charTable[5] = advPowerLevelsChar;
+    charTable[6] = txPowerModeChar;
+    charTable[7] = beaconPeriodChar;
+    charTable[8] = resetChar;
+
+    GattService configService(UUID_URL_BEACON_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+
+    ble.gattServer().addService(configService);
+    ble.gattServer().onDataWritten(this, &EddystoneService::onDataWrittenCallback);
+    updateCharacteristicValues();
+    setupEddystoneConfigAdvertisements();
+}
+
+void EddystoneService::freeConfigCharacteristics(void)
+{
+    delete lockStateChar;
+    delete lockChar;
+    delete unlockChar;
+    delete urlDataChar;
+    delete flagsChar;
+    delete advPowerLevelsChar;
+    delete txPowerModeChar;
+    delete beaconPeriodChar;
+    delete resetChar;
+}
+
+void EddystoneService::freeBeaconFrames(void)
+{
+    delete[] rawUrlFrame;
+    delete[] rawUidFrame;
+    delete[] rawTlmFrame;
+}
+
+void EddystoneService::radioNotificationCallback(bool radioActive)
+{
+    if (radioActive) {
+        /* Do nothing */
+        return;
+    }
+
+    tlmFrame.updatePduCount();
+    currentConsecFrames[currentAdvertisedFrame]++;
+
+    if (consecFrames[currentAdvertisedFrame] > currentConsecFrames[currentAdvertisedFrame]) {
+        if (currentAdvertisedFrame == EDDYSTONE_FRAME_TLM) {
+            /* Update the TLM frame otherwise we will not meet the 0.1 secs resolution of
+             * the Eddystone specification.
+             */
+            updateRawTLMFrame();
+            updateAdvertisementPacket(rawTlmFrame, tlmFrame.getRawFrameSize());
+        }
+        /* Keep advertising the same frame */
+        return;
+    }
+
+    currentConsecFrames[currentAdvertisedFrame] = 0;
+
+#ifdef YOTTA_CFG_MBED_OS
+    minar::Scheduler::postCallback(this, &EddystoneService::swapAdvertisedFrame);
+#else
+    swapAdvertisedFrameTimeout.attach_us(this, &EddystoneService::swapAdvertisedFrame, 1);
+#endif
+}
+
+/*
+ * Internal helper function used to update the GATT database following any
+ * change to the internal state of the service object.
+ */
+void EddystoneService::updateCharacteristicValues(void)
+{
+    ble.gattServer().write(lockStateChar->getValueHandle(), reinterpret_cast<uint8_t *>(&lockState), sizeof(bool));
+    ble.gattServer().write(urlDataChar->getValueHandle(), urlFrame.getEncodedURLData(), urlFrame.getEncodedURLDataLength());
+    ble.gattServer().write(flagsChar->getValueHandle(), &flags, sizeof(uint8_t));
+    ble.gattServer().write(beaconPeriodChar->getValueHandle(), reinterpret_cast<uint8_t *>(&beaconPeriod), sizeof(uint16_t));
+    ble.gattServer().write(txPowerModeChar->getValueHandle(), &txPowerMode, sizeof(uint8_t));
+    ble.gattServer().write(advPowerLevelsChar->getValueHandle(), reinterpret_cast<uint8_t *>(advPowerLevels), sizeof(PowerLevels_t));
+    ble.gattServer().write(lockChar->getValueHandle(), lock, sizeof(PowerLevels_t));
+    ble.gattServer().write(unlockChar->getValueHandle(), unlock, sizeof(PowerLevels_t));
+}
+
+void EddystoneService::setupEddystoneConfigAdvertisements(void)
+{
+    ble.gap().clearAdvertisingPayload();
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+
+    /* UUID is in different order in the ADV frame (!) */
+    uint8_t reversedServiceUUID[sizeof(UUID_URL_BEACON_SERVICE)];
+    for (size_t i = 0; i < sizeof(UUID_URL_BEACON_SERVICE); i++) {
+        reversedServiceUUID[i] = UUID_URL_BEACON_SERVICE[sizeof(UUID_URL_BEACON_SERVICE) - i - 1];
+    }
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, reversedServiceUUID, sizeof(reversedServiceUUID));
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG);
+    ble.gap().accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, reinterpret_cast<const uint8_t *>(&DEVICE_NAME), sizeof(DEVICE_NAME));
+    ble.gap().accumulateScanResponse(
+        GapAdvertisingData::TX_POWER_LEVEL,
+        reinterpret_cast<uint8_t *>(&advPowerLevels[TX_POWER_MODE_LOW]),
+        sizeof(uint8_t));
+
+    ble.gap().setTxPower(radioPowerLevels[txPowerMode]);
+    ble.gap().setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
+    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.gap().setAdvertisingInterval(advConfigInterval);
+    ble.gap().startAdvertising();
+}
+
+void EddystoneService::lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams)
+{
+    if (lockState) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
+    } else if (authParams->len != sizeof(Lock_t)) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
+    } else if (authParams->offset != 0) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
+    } else {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
+    }
+}
+
+void EddystoneService::unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams)
+{
+    if (!lockState && (authParams->len == sizeof(Lock_t))) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
+    } else if (authParams->len != sizeof(Lock_t)) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
+    } else if (authParams->offset != 0) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
+    } else if (memcmp(authParams->data, lock, sizeof(Lock_t)) != 0) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
+    } else {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
+    }
+}
+
+void EddystoneService::urlDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams)
+{
+    if (lockState) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
+    } else if (authParams->offset != 0) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
+    } else {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
+    }
+}
+
+void EddystoneService::powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams)
+{
+    if (lockState) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
+    } else if (authParams->len != sizeof(uint8_t)) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
+    } else if (authParams->offset != 0) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
+    } else if (*((uint8_t *)authParams->data) >= NUM_POWER_MODES) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED;
+    } else {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
+    }
+}
+
+template <typename T>
+void EddystoneService::basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams)
+{
+    if (lockState) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
+    } else if (authParams->len != sizeof(T)) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
+    } else if (authParams->offset != 0) {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
+    } else {
+        authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
+    }
+}
+
+/*
+ * This callback is invoked when a GATT client attempts to modify any of the
+ * characteristics of this service. Attempts to do so are also applied to
+ * the internal state of this service object.
+ */
+void EddystoneService::onDataWrittenCallback(const GattWriteCallbackParams *writeParams)
+{
+    uint16_t handle = writeParams->handle;
+
+    if (handle == lockChar->getValueHandle()) {
+        memcpy(lock, writeParams->data, sizeof(Lock_t));
+        /* Set the state to be locked by the lock code (note: zeros are a valid lock) */
+        lockState = true;
+        ble.gattServer().write(lockChar->getValueHandle(), lock, sizeof(PowerLevels_t));
+        ble.gattServer().write(lockStateChar->getValueHandle(), reinterpret_cast<uint8_t *>(&lockState), sizeof(bool));
+    } else if (handle == unlockChar->getValueHandle()) {
+        /* Validated earlier */
+        lockState = false;
+        ble.gattServer().write(unlockChar->getValueHandle(), unlock, sizeof(PowerLevels_t));
+        ble.gattServer().write(lockStateChar->getValueHandle(), reinterpret_cast<uint8_t *>(&lockState), sizeof(bool));
+    } else if (handle == urlDataChar->getValueHandle()) {
+        urlFrame.setEncodedURLData(writeParams->data, writeParams->len);
+        ble.gattServer().write(urlDataChar->getValueHandle(), urlFrame.getEncodedURLData(), urlFrame.getEncodedURLDataLength());
+    } else if (handle == flagsChar->getValueHandle()) {
+        flags = *(writeParams->data);
+        ble.gattServer().write(flagsChar->getValueHandle(), &flags, sizeof(uint8_t));
+    } else if (handle == advPowerLevelsChar->getValueHandle()) {
+        memcpy(advPowerLevels, writeParams->data, sizeof(PowerLevels_t));
+        ble.gattServer().write(advPowerLevelsChar->getValueHandle(), reinterpret_cast<uint8_t *>(advPowerLevels), sizeof(PowerLevels_t));
+    } else if (handle == txPowerModeChar->getValueHandle()) {
+        txPowerMode = *(writeParams->data);
+        ble.gattServer().write(txPowerModeChar->getValueHandle(), &txPowerMode, sizeof(uint8_t));
+    } else if (handle == beaconPeriodChar->getValueHandle()) {
+        uint16_t tmpBeaconPeriod = correctAdvertisementPeriod(*((uint16_t *)(writeParams->data)));
+        if (tmpBeaconPeriod != beaconPeriod) {
+            beaconPeriod = tmpBeaconPeriod;
+            ble.gattServer().write(beaconPeriodChar->getValueHandle(), reinterpret_cast<uint8_t *>(&beaconPeriod), sizeof(uint16_t));
+        }
+    } else if (handle == resetChar->getValueHandle() && (*((uint8_t *)writeParams->data) != 0)) {
+        /* Reset characteristics to default values */
+        flags        = 0;
+        txPowerMode  = TX_POWER_MODE_LOW;
+        beaconPeriod = DEFAULT_BEACON_PERIOD_MSEC;
+
+        urlFrame.setURLData(DEFAULT_URL);
+        memset(lock, 0, sizeof(Lock_t));
+
+        ble.gattServer().write(urlDataChar->getValueHandle(), urlFrame.getEncodedURLData(), urlFrame.getEncodedURLDataLength());
+        ble.gattServer().write(flagsChar->getValueHandle(), &flags, sizeof(uint8_t));
+        ble.gattServer().write(txPowerModeChar->getValueHandle(), &txPowerMode, sizeof(uint8_t));
+        ble.gattServer().write(beaconPeriodChar->getValueHandle(), reinterpret_cast<uint8_t *>(&beaconPeriod), sizeof(uint16_t));
+        ble.gattServer().write(lockChar->getValueHandle(), lock, sizeof(PowerLevels_t));
+    }
+}
+
+uint16_t EddystoneService::correctAdvertisementPeriod(uint16_t beaconPeriodIn) const
+{
+    /* Re-map beaconPeriod to within permissible bounds if necessary. */
+    if (beaconPeriodIn != 0) {
+        if (beaconPeriodIn < ble.gap().getMinAdvertisingInterval()) {
+            return ble.gap().getMinAdvertisingInterval();
+        } else if (beaconPeriodIn > ble.gap().getMaxAdvertisingInterval()) {
+            return ble.gap().getMaxAdvertisingInterval();
+        }
+    }
+    return beaconPeriodIn;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/Eddystone/EddystoneService.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,238 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+
+#ifndef __EDDYSTONESERVICE_H__
+#define __EDDYSTONESERVICE_H__
+
+#include "ble/BLE.h"
+#include "EddystoneTypes.h"
+#include "URLFrame.h"
+#include "UIDFrame.h"
+#include "TLMFrame.h"
+#include <string.h>
+#ifdef YOTTA_CFG_MBED_OS
+    #include "mbed-drivers/mbed.h"
+#else
+    #include "mbed.h"
+#endif
+
+class EddystoneService
+{
+public:
+    static const uint16_t TOTAL_CHARACTERISTICS = 9;
+
+    static const uint32_t DEFAULT_CONFIG_PERIOD_MSEC = 1000;
+    static const uint16_t DEFAULT_BEACON_PERIOD_MSEC = 1000;
+
+    /* Operation modes of the EddystoneService:
+     *      NONE: EddystoneService has been initialised but no memory has been
+     *            dynamically allocated. Additionally, no services are running
+     *            nothing is being advertised.
+     *      CONFIG: EddystoneService has been initialised, the configuration
+     *              service started and memory has been allocated for BLE
+     *              characteristics. Memory consumption peaks during CONFIG
+     *              mode.
+     *      BEACON: Eddystone service is running as a beacon advertising URL,
+     *              UID and/or TLM frames depending on how it is configured.
+     * Note: The main app can change the mode of EddystoneService at any point
+     * of time by calling startConfigService() or startBeaconService().
+     * Resources from the previous mode will be freed. It is currently NOT
+     * possible to force EddystoneService back into MODE_NONE.
+     */
+    enum OperationModes {
+        EDDYSTONE_MODE_NONE,
+        EDDYSTONE_MODE_CONFIG,
+        EDDYSTONE_MODE_BEACON
+    };
+
+    struct EddystoneParams_t {
+        bool             lockState;
+        Lock_t           lock;
+        Lock_t           unlock;
+        uint8_t          flags;
+        PowerLevels_t    advPowerLevels;
+        uint8_t          txPowerMode;
+        uint16_t         beaconPeriod;
+        uint8_t          tlmVersion;
+        uint8_t          urlDataLength;
+        UrlData_t        urlData;
+        UIDNamespaceID_t uidNamespaceID;
+        UIDInstanceID_t  uidInstanceID;
+    };
+
+    enum EddystoneError_t {
+        EDDYSTONE_ERROR_NONE,
+        EDDYSTONE_ERROR_INVALID_BEACON_PERIOD,
+        EDDYSTONE_ERROR_INVALID_CONSEC_FRAMES,
+        EDDYSTONE_ERROR_INVALID_ADVERTISING_INTERVAL
+    };
+
+    enum FrameType {
+        EDDYSTONE_FRAME_URL,
+        EDDYSTONE_FRAME_UID,
+        EDDYSTONE_FRAME_TLM,
+        NUM_EDDYSTONE_FRAMES
+    };
+
+    /* Initialise the EddystoneService using parameters from persistent storage */
+    EddystoneService(BLE                 &bleIn,
+                     EddystoneParams_t   &paramsIn,
+                     const PowerLevels_t &advPowerLevelsIn,
+                     const PowerLevels_t &radioPowerLevelsIn,
+                     uint32_t            advConfigIntervalIn = DEFAULT_CONFIG_PERIOD_MSEC);
+
+    /* When using this constructor we need to call setURLData,
+     * setTMLData and setUIDData to initialise values manually
+     */
+    EddystoneService(BLE                 &bleIn,
+                     const PowerLevels_t &advPowerLevelsIn,
+                     const PowerLevels_t &radioPowerLevelsIn,
+                     uint32_t            advConfigIntervalIn = DEFAULT_CONFIG_PERIOD_MSEC);
+
+    /* Setup callback to update BatteryVoltage in TLM frame */
+    void onTLMBatteryVoltageUpdate(TlmUpdateCallback_t tlmBatteryVoltageCallbackIn);
+
+    /* Setup callback to update BeaconTemperature in TLM frame */
+    void onTLMBeaconTemperatureUpdate(TlmUpdateCallback_t tlmBeaconTemperatureCallbackIn);
+
+    void setTLMData(uint8_t tlmVersionIn = 0);
+
+    void setURLData(const char *urlDataIn);
+
+    void setUIDData(const UIDNamespaceID_t *uidNamespaceIDIn, const UIDInstanceID_t *uidInstanceIDIn);
+
+    EddystoneError_t startConfigService(void);
+
+    EddystoneError_t startBeaconService(uint16_t consecUrlFramesIn = 2, uint16_t consecUidFramesIn = 2, uint16_t consecTlmFramesIn = 2);
+
+    /* It is not the responsibility of the Eddystone implementation to store
+     * the configured parameters in persistent storage since this is
+     * platform-specific. So we provide this function that returns the
+     * configured values that need to be stored and the main application
+     * takes care of storing them.
+     */
+    void getEddystoneParams(EddystoneParams_t *params);
+
+private:
+    /* Helper function used only once during constructing the object to avoid
+     * duplicated code.
+     */
+    void eddystoneConstructorHelper(const PowerLevels_t &advPowerLevelsIn,
+                                    const PowerLevels_t &radioPowerLevelsIn,
+                                    uint32_t            advConfigIntervalIn);
+
+    /* When changing modes, we shutdown and init the BLE instance, so
+     * this is needed to complete the initialisation task.
+     */
+    void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext);
+
+    void swapAdvertisedFrame(void);
+
+    void updateAdvertisementPacket(const uint8_t* rawFrame, size_t rawFrameLength);
+
+    /* Helper function that calls user-defined functions to update Battery Voltage and Temperature (if available),
+     * then updates the raw frame data and finally updates the actual advertised packet. This operation must be
+     * done fairly often because the TLM frame TimeSinceBoot must have a 0.1 secs resolution according to the
+     * Eddystone specification.
+     */
+    void updateRawTLMFrame(void);
+
+    void setupBeaconService(void);
+
+    void setupConfigService(void);
+
+    void freeConfigCharacteristics(void);
+
+    void freeBeaconFrames(void);
+
+    void radioNotificationCallback(bool radioActive);
+
+    /*
+     * Internal helper function used to update the GATT database following any
+     * change to the internal state of the service object.
+     */
+    void updateCharacteristicValues(void);
+
+    void setupEddystoneConfigAdvertisements(void);
+
+    void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
+
+    void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
+
+    void urlDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
+
+    void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
+
+    template <typename T>
+    void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams);
+
+    /*
+     * This callback is invoked when a GATT client attempts to modify any of the
+     * characteristics of this service. Attempts to do so are also applied to
+     * the internal state of this service object.
+     */
+    void onDataWrittenCallback(const GattWriteCallbackParams *writeParams);
+
+    uint16_t correctAdvertisementPeriod(uint16_t beaconPeriodIn) const;
+
+    BLE                                                             &ble;
+    uint32_t                                                        advConfigInterval;
+    uint8_t                                                         operationMode;
+
+    URLFrame                                                        urlFrame;
+    UIDFrame                                                        uidFrame;
+    TLMFrame                                                        tlmFrame;
+
+    PowerLevels_t                                                   radioPowerLevels;
+    PowerLevels_t                                                   advPowerLevels;
+    bool                                                            lockState;
+    bool                                                            resetFlag;
+    Lock_t                                                          lock;
+    Lock_t                                                          unlock;
+    uint8_t                                                         flags;
+    uint8_t                                                         txPowerMode;
+    uint16_t                                                        beaconPeriod;
+
+    ReadOnlyGattCharacteristic<bool>                                *lockStateChar;
+    WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(Lock_t)>       *lockChar;
+    WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(Lock_t)>       *unlockChar;
+    GattCharacteristic                                              *urlDataChar;
+    ReadWriteGattCharacteristic<uint8_t>                            *flagsChar;
+    ReadWriteArrayGattCharacteristic<int8_t, sizeof(PowerLevels_t)> *advPowerLevelsChar;
+    ReadWriteGattCharacteristic<uint8_t>                            *txPowerModeChar;
+    ReadWriteGattCharacteristic<uint16_t>                           *beaconPeriodChar;
+    WriteOnlyGattCharacteristic<bool>                               *resetChar;
+
+    uint8_t                                                         *rawUrlFrame;
+    uint8_t                                                         *rawUidFrame;
+    uint8_t                                                         *rawTlmFrame;
+
+    uint16_t                                                        consecFrames[NUM_EDDYSTONE_FRAMES];
+    uint16_t                                                        currentConsecFrames[NUM_EDDYSTONE_FRAMES];
+    uint8_t                                                         currentAdvertisedFrame;
+
+    TlmUpdateCallback_t                                             tlmBatteryVoltageCallback;
+    TlmUpdateCallback_t                                             tlmBeaconTemperatureCallback;
+
+    Timer                                                           timeSinceBootTimer;
+#ifndef YOTTA_CFG_MBED_OS
+    Timeout                                                         swapAdvertisedFrameTimeout;
+#endif
+
+    GattCharacteristic                                              *charTable[TOTAL_CHARACTERISTICS];
+};
+
+#endif  /* __EDDYSTONESERVICE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/Eddystone/EddystoneTypes.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,72 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+
+#ifndef __EDDYSTONETYPES_H__
+#define __EDDYSTONETYPES_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define UUID_URL_BEACON(FIRST, SECOND) {                         \
+        0xee, 0x0c, FIRST, SECOND, 0x87, 0x86, 0x40, 0xba,       \
+        0xab, 0x96, 0x99, 0xb9, 0x1a, 0xc9, 0x81, 0xd8,          \
+}
+
+const uint8_t EDDYSTONE_UUID[] = {0xAA, 0xFE};
+
+const uint8_t UUID_URL_BEACON_SERVICE[]    = UUID_URL_BEACON(0x20, 0x80);
+const uint8_t UUID_LOCK_STATE_CHAR[]       = UUID_URL_BEACON(0x20, 0x81);
+const uint8_t UUID_LOCK_CHAR[]             = UUID_URL_BEACON(0x20, 0x82);
+const uint8_t UUID_UNLOCK_CHAR[]           = UUID_URL_BEACON(0x20, 0x83);
+const uint8_t UUID_URL_DATA_CHAR[]         = UUID_URL_BEACON(0x20, 0x84);
+const uint8_t UUID_FLAGS_CHAR[]            = UUID_URL_BEACON(0x20, 0x85);
+const uint8_t UUID_ADV_POWER_LEVELS_CHAR[] = UUID_URL_BEACON(0x20, 0x86);
+const uint8_t UUID_TX_POWER_MODE_CHAR[]    = UUID_URL_BEACON(0x20, 0x87);
+const uint8_t UUID_BEACON_PERIOD_CHAR[]    = UUID_URL_BEACON(0x20, 0x88);
+const uint8_t UUID_RESET_CHAR[]            = UUID_URL_BEACON(0x20, 0x89);
+
+const char DEVICE_NAME[] = "EDDYSTONE CONFIG";
+
+const char DEFAULT_URL[] = "http://www.mbed.com/";
+
+enum PowerModes {
+    TX_POWER_MODE_LOWEST,
+    TX_POWER_MODE_LOW,
+    TX_POWER_MODE_MEDIUM,
+    TX_POWER_MODE_HIGH,
+    NUM_POWER_MODES
+};
+
+/* 128 bits of lock */
+typedef uint8_t Lock_t[16];
+typedef int8_t PowerLevels_t[NUM_POWER_MODES];
+
+const uint16_t URL_DATA_MAX = 18;
+typedef uint8_t UrlData_t[URL_DATA_MAX];
+
+/* UID Frame Type subfields */
+const size_t UID_NAMESPACEID_SIZE = 10;
+typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
+const size_t UID_INSTANCEID_SIZE = 6;
+typedef uint8_t UIDInstanceID_t[UID_INSTANCEID_SIZE];
+
+/* Callbacks for updating BateryVoltage and Temperature */
+typedef uint16_t (*TlmUpdateCallback_t) (uint16_t);
+
+/* Size of Eddystone UUID needed for all frames */
+const uint16_t EDDYSTONE_UUID_SIZE = sizeof(EDDYSTONE_UUID);
+
+#endif /* __EDDYSTONETYPES_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/Eddystone/TLMFrame.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,105 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+
+#include "TLMFrame.h"
+
+TLMFrame::TLMFrame(uint8_t  tlmVersionIn,
+                   uint16_t tlmBatteryVoltageIn,
+                   uint16_t tlmBeaconTemperatureIn,
+                   uint32_t tlmPduCountIn,
+                   uint32_t tlmTimeSinceBootIn) :
+    tlmVersion(tlmVersionIn),
+    lastTimeSinceBootRead(0),
+    tlmBatteryVoltage(tlmBatteryVoltageIn),
+    tlmBeaconTemperature(tlmBeaconTemperatureIn),
+    tlmPduCount(tlmPduCountIn),
+    tlmTimeSinceBoot(tlmTimeSinceBootIn)
+{
+}
+
+void TLMFrame::setTLMData(uint8_t tlmVersionIn)
+{
+    /* According to the Eddystone spec BatteryVoltage is 0 and
+     * BeaconTemperature is 0x8000 if not supported
+     */
+    tlmVersion           = tlmVersionIn;
+    tlmBatteryVoltage    = 0;
+    tlmBeaconTemperature = 0x8000;
+    tlmPduCount          = 0;
+    tlmTimeSinceBoot     = 0;
+}
+
+void TLMFrame::constructTLMFrame(uint8_t *rawFrame)
+{
+    size_t index = 0;
+    rawFrame[index++] = EDDYSTONE_UUID[0];                    // 16-bit Eddystone UUID
+    rawFrame[index++] = EDDYSTONE_UUID[1];
+    rawFrame[index++] = FRAME_TYPE_TLM;                       // Eddystone frame type = Telemetry
+    rawFrame[index++] = tlmVersion;                           // TLM Version Number
+    rawFrame[index++] = (uint8_t)(tlmBatteryVoltage >> 8);    // Battery Voltage[0]
+    rawFrame[index++] = (uint8_t)(tlmBatteryVoltage >> 0);    // Battery Voltage[1]
+    rawFrame[index++] = (uint8_t)(tlmBeaconTemperature >> 8); // Beacon Temp[0]
+    rawFrame[index++] = (uint8_t)(tlmBeaconTemperature >> 0); // Beacon Temp[1]
+    rawFrame[index++] = (uint8_t)(tlmPduCount >> 24);         // PDU Count [0]
+    rawFrame[index++] = (uint8_t)(tlmPduCount >> 16);         // PDU Count [1]
+    rawFrame[index++] = (uint8_t)(tlmPduCount >> 8);          // PDU Count [2]
+    rawFrame[index++] = (uint8_t)(tlmPduCount >> 0);          // PDU Count [3]
+    rawFrame[index++] = (uint8_t)(tlmTimeSinceBoot >> 24);    // Time Since Boot [0]
+    rawFrame[index++] = (uint8_t)(tlmTimeSinceBoot >> 16);    // Time Since Boot [1]
+    rawFrame[index++] = (uint8_t)(tlmTimeSinceBoot >> 8);     // Time Since Boot [2]
+    rawFrame[index++] = (uint8_t)(tlmTimeSinceBoot >> 0);     // Time Since Boot [3]
+}
+
+size_t TLMFrame::getRawFrameSize(void) const
+{
+    return FRAME_SIZE_TLM + EDDYSTONE_UUID_SIZE;
+}
+
+void TLMFrame::updateTimeSinceBoot(uint32_t nowInMillis)
+{
+    tlmTimeSinceBoot      += (nowInMillis - lastTimeSinceBootRead) / 100;
+    lastTimeSinceBootRead  = nowInMillis;
+}
+
+void TLMFrame::updateBatteryVoltage(uint16_t tlmBatteryVoltageIn)
+{
+    tlmBatteryVoltage = tlmBatteryVoltageIn;
+}
+
+void TLMFrame::updateBeaconTemperature(uint16_t tlmBeaconTemperatureIn)
+{
+    tlmBeaconTemperature = tlmBeaconTemperatureIn;
+}
+
+void TLMFrame::updatePduCount(void)
+{
+    tlmPduCount++;
+}
+
+uint16_t TLMFrame::getBatteryVoltage(void) const
+{
+    return tlmBatteryVoltage;
+}
+
+uint16_t TLMFrame::getBeaconTemperature(void) const
+{
+    return tlmBeaconTemperature;
+}
+
+uint8_t TLMFrame::getTLMVersion(void) const
+{
+    return tlmVersion;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/Eddystone/TLMFrame.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,63 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+
+#ifndef __TLMFRAME_H__
+#define __TLMFRAME_H__
+
+#include "EddystoneTypes.h"
+
+class TLMFrame
+{
+public:
+    TLMFrame(uint8_t  tlmVersionIn           = 0,
+             uint16_t tlmBatteryVoltageIn    = 0,
+             uint16_t tlmBeaconTemperatureIn = 0x8000,
+             uint32_t tlmPduCountIn          = 0,
+             uint32_t tlmTimeSinceBootIn     = 0);
+
+    void setTLMData(uint8_t tlmVersionIn = 0);
+
+    void constructTLMFrame(uint8_t *rawFrame);
+
+    size_t getRawFrameSize(void) const;
+
+    void updateTimeSinceBoot(uint32_t nowInMillis);
+
+    void updateBatteryVoltage(uint16_t tlmBatteryVoltageIn);
+
+    void updateBeaconTemperature(uint16_t tlmBeaconTemperatureIn);
+
+    void updatePduCount(void);
+
+    uint16_t getBatteryVoltage(void) const;
+
+    uint16_t getBeaconTemperature(void) const;
+
+    uint8_t getTLMVersion(void) const;
+
+private:
+    static const uint8_t FRAME_TYPE_TLM = 0x20;
+    static const uint8_t FRAME_SIZE_TLM = 14;
+
+    uint8_t              tlmVersion;
+    uint32_t             lastTimeSinceBootRead;
+    uint16_t             tlmBatteryVoltage;
+    uint16_t             tlmBeaconTemperature;
+    uint32_t             tlmPduCount;
+    uint32_t             tlmTimeSinceBoot;
+};
+
+#endif  /* __TLMFRAME_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/Eddystone/UIDFrame.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,67 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+
+#include "UIDFrame.h"
+
+UIDFrame::UIDFrame(void)
+{
+    memset(uidNamespaceID, 0, sizeof(UIDNamespaceID_t));
+    memset(uidInstanceID,  0,  sizeof(UIDInstanceID_t));
+}
+
+UIDFrame::UIDFrame(const UIDNamespaceID_t uidNamespaceIDIn, const UIDInstanceID_t  uidInstanceIDIn)
+{
+    memcpy(uidNamespaceID, uidNamespaceIDIn, sizeof(UIDNamespaceID_t));
+    memcpy(uidInstanceID,  uidInstanceIDIn,  sizeof(UIDInstanceID_t));
+}
+
+void UIDFrame::setUIDData(const UIDNamespaceID_t *uidNamespaceIDIn, const UIDInstanceID_t *uidInstanceIDIn)
+{
+    memcpy(uidNamespaceID, uidNamespaceIDIn, sizeof(UIDNamespaceID_t));
+    memcpy(uidInstanceID,  uidInstanceIDIn,  sizeof(UIDInstanceID_t));
+}
+
+void UIDFrame::constructUIDFrame(uint8_t *rawFrame, int8_t advPowerLevel)
+{
+    size_t index = 0;
+
+    rawFrame[index++] = EDDYSTONE_UUID[0];                                   // 16-bit Eddystone UUID
+    rawFrame[index++] = EDDYSTONE_UUID[1];
+    rawFrame[index++] = FRAME_TYPE_UID;                                      // 1B  Type
+    rawFrame[index++] = advPowerLevel;                                       // 1B  Power @ 0meter
+
+    memcpy(rawFrame + index, uidNamespaceID, sizeof(UIDNamespaceID_t));      // 10B Namespace ID
+    index += sizeof(UIDNamespaceID_t);
+    memcpy(rawFrame + index, uidInstanceID, sizeof(UIDInstanceID_t));        // 6B Instance ID
+    index += sizeof(UIDInstanceID_t);
+
+    memset(rawFrame + index, 0, 2 * sizeof(uint8_t));                        // 2B RFU, which are unused
+}
+
+size_t UIDFrame::getRawFrameSize(void) const
+{
+    return FRAME_SIZE_UID + EDDYSTONE_UUID_SIZE;
+}
+
+uint8_t* UIDFrame::getUIDNamespaceID(void)
+{
+    return uidNamespaceID;
+}
+
+uint8_t* UIDFrame::getUIDInstanceID(void)
+{
+    return uidInstanceID;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/Eddystone/UIDFrame.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,48 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+
+#ifndef __UIDFRAME_H__
+#define __UIDFRAME_H__
+
+#include <string.h>
+#include "EddystoneTypes.h"
+
+class UIDFrame
+{
+public:
+    UIDFrame(void);
+
+    UIDFrame(const UIDNamespaceID_t uidNamespaceIDIn, const UIDInstanceID_t  uidInstanceIDIn);
+
+    void setUIDData(const UIDNamespaceID_t *uidNamespaceIDIn, const UIDInstanceID_t *uidInstanceIDIn);
+
+    void constructUIDFrame(uint8_t *rawFrame, int8_t advPowerLevel);
+
+    size_t getRawFrameSize(void) const;
+
+    uint8_t* getUIDNamespaceID(void);
+
+    uint8_t* getUIDInstanceID(void);
+
+private:
+    static const uint8_t FRAME_TYPE_UID = 0x00;
+    static const uint8_t FRAME_SIZE_UID = 20;
+
+    UIDNamespaceID_t     uidNamespaceID;
+    UIDInstanceID_t      uidInstanceID;
+};
+
+#endif  /* __UIDFRAME_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/Eddystone/URLFrame.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,141 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+
+#include "URLFrame.h"
+
+URLFrame::URLFrame(void)
+{
+    urlDataLength = 0;
+    memset(urlData, 0, sizeof(UrlData_t));
+}
+
+URLFrame::URLFrame(const char *urlDataIn)
+{
+    encodeURL(urlDataIn);
+}
+
+URLFrame::URLFrame(UrlData_t urlDataIn, uint8_t urlDataLength)
+{
+    if (urlDataLength > URL_DATA_MAX) {
+        memcpy(urlData, urlDataIn, URL_DATA_MAX);
+    } else {
+        memcpy(urlData, urlDataIn, urlDataLength);
+    }
+}
+
+void URLFrame::constructURLFrame(uint8_t* rawFrame, int8_t advPowerLevel)
+{
+    size_t index = 0;
+    rawFrame[index++] = EDDYSTONE_UUID[0];            // 16-bit Eddystone UUID
+    rawFrame[index++] = EDDYSTONE_UUID[1];
+    rawFrame[index++] = FRAME_TYPE_URL;               // 1B  Type
+    rawFrame[index++] = advPowerLevel;                // 1B  Power @ 0meter
+    memcpy(rawFrame + index, urlData, urlDataLength); // Encoded URL
+}
+
+size_t URLFrame::getRawFrameSize(void) const
+{
+    return urlDataLength + FRAME_MIN_SIZE_URL + EDDYSTONE_UUID_SIZE;
+}
+
+uint8_t* URLFrame::getEncodedURLData(void)
+{
+    return urlData;
+}
+
+uint8_t URLFrame::getEncodedURLDataLength(void) const
+{
+    return urlDataLength;
+}
+
+void URLFrame::setURLData(const char *urlDataIn)
+{
+    encodeURL(urlDataIn);
+}
+
+void URLFrame::setEncodedURLData(const uint8_t* urlEncodedDataIn, const uint8_t urlEncodedDataLengthIn)
+{
+    urlDataLength = urlEncodedDataLengthIn;
+    memcpy(urlData, urlEncodedDataIn, urlEncodedDataLengthIn);
+}
+
+void URLFrame::encodeURL(const char *urlDataIn)
+{
+    const char  *prefixes[] = {
+        "http://www.",
+        "https://www.",
+        "http://",
+        "https://",
+    };
+    const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
+    const char  *suffixes[]   = {
+        ".com/",
+        ".org/",
+        ".edu/",
+        ".net/",
+        ".info/",
+        ".biz/",
+        ".gov/",
+        ".com",
+        ".org",
+        ".edu",
+        ".net",
+        ".info",
+        ".biz",
+        ".gov"
+    };
+    const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
+
+    urlDataLength = 0;
+    memset(urlData, 0, sizeof(UrlData_t));
+
+    if ((urlDataIn == NULL) || (strlen(urlDataIn) == 0)) {
+        return;
+    }
+
+    /*
+     * handle prefix
+     */
+    for (size_t i = 0; i < NUM_PREFIXES; i++) {
+        size_t prefixLen = strlen(prefixes[i]);
+        if (strncmp(urlDataIn, prefixes[i], prefixLen) == 0) {
+            urlData[urlDataLength++]  = i;
+            urlDataIn                      += prefixLen;
+            break;
+        }
+    }
+
+    /*
+     * handle suffixes
+     */
+    while (*urlDataIn && (urlDataLength < URL_DATA_MAX)) {
+        /* check for suffix match */
+        size_t i;
+        for (i = 0; i < NUM_SUFFIXES; i++) {
+            size_t suffixLen = strlen(suffixes[i]);
+            if (strncmp(urlDataIn, suffixes[i], suffixLen) == 0) {
+                urlData[urlDataLength++]  = i;
+                urlDataIn                      += suffixLen;
+                break; /* from the for loop for checking against suffixes */
+            }
+        }
+        /* This is the default case where we've got an ordinary character which doesn't match a suffix. */
+        if (i == NUM_SUFFIXES) {
+            urlData[urlDataLength++] = *urlDataIn;
+            ++urlDataIn;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/Eddystone/URLFrame.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,56 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+
+#ifndef __URLFRAME_H__
+#define __URLFRAME_H__
+
+#include "EddystoneTypes.h"
+#include <string.h>
+
+class URLFrame
+{
+public:
+    URLFrame(void);
+
+    URLFrame(const char *urlDataIn);
+
+    URLFrame(UrlData_t urlDataIn, uint8_t urlDataLength);
+
+    void constructURLFrame(uint8_t* rawFrame, int8_t advPowerLevel);
+
+    size_t getRawFrameSize(void) const;
+
+    uint8_t* getEncodedURLData(void);
+
+    uint8_t getEncodedURLDataLength(void) const;
+
+    void setURLData(const char *urlDataIn);
+
+    void setEncodedURLData(const uint8_t* urlEncodedDataIn, const uint8_t urlEncodedDataLengthIn);
+
+private:
+    void encodeURL(const char *urlDataIn);
+
+    static const uint8_t FRAME_TYPE_URL     = 0x10;
+    /* Even if the URL is 0 bytes we still need to include the type and txPower i.e. 2 bytes */
+    static const uint8_t FRAME_MIN_SIZE_URL = 2;
+
+    uint8_t              urlDataLength;
+    UrlData_t            urlData;
+
+};
+
+#endif /* __URLFRAME_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2_EddyStoneBeacon/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,165 @@
+/* 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.
+ */
+
+/*
+ *  /////// Works well on TYBLE16 Module ///////
+ *  Modified by Kenji Arai
+ *      http://www.page.sannet.ne.jp/kenjia/index.html
+ *      https://os.mbed.com/users/kenjiArai/
+ *
+ *      Started:  Feburary   18th, 2018
+ *      Revised:  April      14th, 2018
+ *
+ *  Original:
+ *      nRF51822_SimpleControls
+ *      https://developer.mbed.org/teams
+ *                      /Bluetooth-Low-Energy/code/BLE_EddystoneBeacon_Service/
+ *  Tested Controller Device:
+ *      iPhone6 Physical Web (PhyWeb) By Viet Hoa Dinh
+ *      https://itunes.apple.com/us/app/physical-web/id927653608?mt=8
+ */
+
+//#define EXAMPLE_2_EDDYSTONE_BEACON
+#ifdef EXAMPLE_2_EDDYSTONE_BEACON
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "TYBLE16_BASE.h"
+#include "BLE.h"
+//#include "EddystoneService.h"
+#include "../Eddystone/EddystoneService.h"
+
+//  Object ---------------------------------------------------------------------
+DigitalOut  led(P0_5);
+Serial      pc(USBTX, USBRX);
+
+//  Definition -----------------------------------------------------------------
+
+//  RAM ------------------------------------------------------------------------
+EddystoneService    *eddyServicePtr;
+Gap::Address_t      my_mac;
+
+//  ROM / Constant data --------------------------------------------------------
+char *const opngmsg =
+    "\x1b[2J\x1b[H"__FILE__ "\r\n"__DATE__ " " __TIME__ " (UTC)\r\n""\r\n";
+
+//  Function prototypes --------------------------------------------------------
+int8_t check_dice(void);
+uint16_t update_vdd(uint16_t x);
+uint16_t update_temp(uint16_t x);
+void onBleInitError(BLE::InitializationCompleteCallbackContext* initContext);
+void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+// !!!!!!!! Please select number of 0 to 6 !!!!!!!!!!!!!!!!!
+int8_t check_dice(void)
+{
+    return 5;
+}
+
+void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext)
+{
+    BLE         &ble  = initContext->ble;
+    ble_error_t error = initContext->error;
+
+    if (error != BLE_ERROR_NONE) {
+        onBleInitError(initContext);
+        return;
+    }
+    // Set UID and TLM frame data
+    const UIDNamespaceID_t uidNamespaceID =
+    {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99};
+    const UIDInstanceID_t  uidInstanceID  =
+    {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
+    uint8_t tlmVersion = 0x00;
+
+    Gap::AddressType_t my_mac_type;
+    ble.gap().getAddress(&my_mac_type, my_mac);
+    // Initialize a EddystoneBeaconConfig service
+    // Values for ADV packets related to firmware levels,
+    // calibrated based on measured values at 1m
+    static const PowerLevels_t defaultAdvPowerLevels = {-47, -33, -21, -13};
+    // Values for radio power levels, provided by manufacturer.
+    static const PowerLevels_t radioPowerLevels      = {-30, -16, -4, 4};
+    eddyServicePtr = new EddystoneService(ble,
+                                          defaultAdvPowerLevels,
+                                          radioPowerLevels);
+    // created short cut web addres by http://bitly.oshiire.org/
+    switch (check_dice()) {
+        case 1:     // Switch sience(mbed)
+            eddyServicePtr->setURLData("http://bit.ly/1oJh91B");
+            break;
+        case 2:    // switch sience(HP)
+            eddyServicePtr->setURLData("http://bit.ly/1oJhP7g");
+            break;
+        case 3:    // Taiyo Yuden BLE
+            eddyServicePtr->setURLData("http://bit.ly/1VvuCVr");
+            break;
+        case 4:    // Taiyo Yuden
+            eddyServicePtr->setURLData("http://bit.ly/1Vvtp0l");
+            break;
+        case 5:    // JH1PJL(mbed)
+            eddyServicePtr->setURLData("http://bit.ly/1Vvt51J");
+            break;
+        case 6:    // JH1PJL(HP)
+            eddyServicePtr->setURLData("http://bit.ly/1VvteT0");
+            break;
+        case 0:
+        default:   // Mbed
+            eddyServicePtr->setURLData("http://mbed.org");
+            break;
+    }
+    eddyServicePtr->setUIDData(&uidNamespaceID, &uidInstanceID);
+    eddyServicePtr->setTLMData(tlmVersion);
+    // Start Eddystone in config mode
+    eddyServicePtr->startBeaconService(5, 5, 5);
+}
+
+int main(void)
+{
+    pc.puts(opngmsg);
+    led = 1;
+    // Check TYBLE-16 configuration
+    cpu_sys();
+    if (compile_condition() == false) {
+        pc.printf("This is wrong configuration!!\r\n");
+        while(true) {
+            led = !led;
+            wait(0.2);
+        }
+    }
+    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
+    ble.init(bleInitComplete);
+    while (ble.hasInitialized() == false) {
+        ;
+    }
+    //
+    led = 0;
+    //pc.printf("line:%d\r\n", __LINE__);
+    while (true) {
+        ble.waitForEvent();
+    }
+}
+
+void onBleInitError(BLE::InitializationCompleteCallbackContext* initContext)
+{
+    // Initialization error handling goes here...
+    (void) initContext;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/3_Heart_Rate/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,162 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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.
+ */
+/*
+    Modified by Kenji Arai, April 14th, 2018
+        https://os.mbed.com/users/kenjiArai/
+ */
+
+//#define EXAMPLE_3_HEART_RATE
+#ifdef EXAMPLE_3_HEART_RATE
+
+#include "mbed.h"
+#include "events/mbed_events.h"
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "ble/services/HeartRateService.h"
+#include "ble/services/BatteryService.h"
+#include "ble/services/DeviceInformationService.h"
+#include "TYBLE16_BASE.h"
+
+DigitalOut  led1(LED1, 1);
+Serial      pc(USBTX, USBRX);
+
+const static char     DEVICE_NAME[] = "TYBLE16";
+char *const opngmsg =
+    "\x1b[2J\x1b[H"__FILE__ "\r\n"__DATE__ " " __TIME__ " (UTC)\r\n""\r\n";
+
+static const uint16_t uuid16_list[] = {
+    GattService::UUID_HEART_RATE_SERVICE,
+    GattService::UUID_DEVICE_INFORMATION_SERVICE
+};
+
+static volatile bool  triggerSensorPolling = false;
+
+uint8_t hrmCounter = 100; // init HRM to 100bps
+
+HeartRateService         *hrService;
+DeviceInformationService *deviceInfo;
+
+void disconnectionCallback(
+    const Gap::DisconnectionCallbackParams_t *params
+)
+{
+    // restart advertising
+    BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
+}
+
+void periodicCallback(void)
+{
+    led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
+
+    /* Note that the periodicCallback() executes in interrupt context,
+     * so it is safer to do
+     * heavy-weight sensor polling from the main thread. */
+    triggerSensorPolling = true;
+}
+
+void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
+{
+    BLE &ble          = params->ble;
+    ble_error_t error = params->error;
+
+    if (error != BLE_ERROR_NONE) {
+        return;
+    }
+
+    ble.gap().onDisconnection(disconnectionCallback);
+
+    /* Setup primary service. */
+    hrService = new HeartRateService(
+        ble,
+        hrmCounter,
+        HeartRateService::LOCATION_FINGER
+    );
+
+    /* Setup auxiliary service. */
+    deviceInfo = new DeviceInformationService(
+        ble,
+        "ARM",
+        "Model1",
+        "SN1",
+        "hw-rev1",
+        "fw-rev1",
+        "soft-rev1"
+    );
+
+    /* Setup advertising. */
+    ble.gap().accumulateAdvertisingPayload(
+        GapAdvertisingData::BREDR_NOT_SUPPORTED |
+        GapAdvertisingData::LE_GENERAL_DISCOVERABLE
+    );
+    ble.gap().accumulateAdvertisingPayload(
+        GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
+        (uint8_t *)uuid16_list, sizeof(uuid16_list)
+    );
+    ble.gap().accumulateAdvertisingPayload(
+        GapAdvertisingData::GENERIC_HEART_RATE_SENSOR
+    );
+    ble.gap().accumulateAdvertisingPayload(
+        GapAdvertisingData::COMPLETE_LOCAL_NAME,
+        (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)
+    );
+    ble.gap().setAdvertisingType(
+        GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED
+    );
+    ble.gap().setAdvertisingInterval(1000); /* 1000ms */
+    ble.gap().startAdvertising();
+}
+
+int main(void)
+{
+    pc.puts(opngmsg);
+    led1 = 1;
+    Ticker ticker;
+    ticker.attach(periodicCallback, 1);     // blink LED every second
+
+    // Check TYBLE-16 configuration
+    cpu_sys();
+    compile_condition();
+    //
+    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
+    ble.init(bleInitComplete);
+
+    /* SpinWait for initialization to complete. This is necessary
+     * because the BLE object is used in the main loop below. */
+    while (ble.hasInitialized()  == false) {
+        /* spin loop */
+    }
+
+    // infinite loop
+    while (true) {
+        // check for trigger from periodicCallback()
+        if (triggerSensorPolling && ble.getGapState().connected) {
+            triggerSensorPolling = false;
+
+            // Do blocking calls or whatever is necessary for sensor polling.
+            // In our case, we simply update the HRM measurement.
+            hrmCounter++;
+            if (hrmCounter == 175) { //  100 <= HRM bps <=175
+                hrmCounter = 100;
+            }
+
+            hrService->updateHeartRate(hrmCounter);
+        } else {
+            ble.waitForEvent(); // low power wait for event
+        }
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4_RCBController/RCBController.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,74 @@
+/*
+ *		Modifed by Kenji Arai on December 31st, 2015
+ */
+
+typedef union {
+    struct  {
+        /*
+        1st and 2nd byte: buttom
+         UP: 0x0001
+         DOWN: 0x0002
+         RIGHT: 0x0004
+         LEFT: 0x0008
+         Y button: 0x0010
+         A button: 0x0020
+         B button: 0x0040
+         X button: 0x0100
+         L1: 0x0200
+         L2: 0x0400
+         R1: 0x0800
+         R2: 0x1000
+         START: 0x0003
+         SELECT: 0x000C
+        */
+        unsigned X		: 1;
+        unsigned L1		: 1;
+        unsigned L2		: 1;
+        unsigned R1		: 1;
+        unsigned R2		: 1;
+        unsigned space1	: 3;
+        unsigned UP		: 1;
+        unsigned DOWN	: 1;
+        unsigned RIGHT	: 1;
+        unsigned LEFT	: 1;
+        unsigned Y		: 1;
+        unsigned A		: 1;
+        unsigned B		: 1;
+        unsigned space2	: 1;
+        /*
+        3rd and 4th byte: Analog value (left side)
+         Left to Right: 1-255 (Neutral=128)
+         Down to UP   : 1-255 (Neutral=128)
+        */
+        unsigned LeftAnalogLR:8;
+        unsigned LeftAnalogUD:8;
+        /*
+        5th to 6th byte: Analog value (Right side)
+         Left to Right: 1-255 (Neutral=128)
+         Down to UP   : 1-255 (Neutral=128)
+        */
+        unsigned RightAnalogLR:8;
+        unsigned RightAnalogUD:8;
+        /*
+        7th to 9th byte: Accel
+         X-axis: 1-255 (Neutral=128)
+         Y-axis: 1-255 (Neutral=128)
+         Z-axis: 1-255 (Neutral=128)
+        */
+        unsigned AcceleX:8;
+        unsigned AcceleY:8;
+        unsigned AcceleZ:8;
+        /*
+        10th byte       : Setting parameter
+         7th and 6th bit: setting accel (0-3)
+         5th bit        : Analog-Left (0 or 1)
+         4th bit        : Analog-Right (0 or 1)
+         3th to 1st bit : iOS device direction (1-4)
+        */
+        unsigned DEV_DIR:4;
+        unsigned RIGHT_ANALOG:1;
+        unsigned LEFT_ANALOG:1;
+        unsigned ACCELE_SETTING:2;
+    } status;
+    unsigned char data[10];
+} RCBController;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4_RCBController/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,162 @@
+/*
+ *      December 31st, 2015     Modified by Kenji Arai
+ *		January  19th, 2016
+ *		October  12th, 2017		!! Run on Mbed-os5
+ *                              http://www.page.sannet.ne.jp/kenjia/index.html
+ *                              https://os.mbed.com/users/kenjiArai/
+ *		April    14th, 2018		run on TYBLE16
+ *
+ *  Original:
+ *   BLE_RCBController2_Motor
+ *   https://developer.mbed.org/users/robo8080/code/BLE_RCBController2_Motor/
+ *  Tested Controller Device:
+ *   iPhone6 RCBController (Ver1.4.0)
+ *   https://itunes.apple.com/jp/app/rcbcontroller/id689724127?mt=8
+ */
+
+//#define EXAMPLE_4_RCB_CONTROLLER
+#ifdef EXAMPLE_4_RCB_CONTROLLER
+
+#include "mbed.h"
+#include "BLE.h"
+#include "RCBController.h"
+#include "TYBLE16_BASE.h"
+
+#define NEED_CONSOLE_OUTPUT	 1 // Keep 1
+
+#if NEED_CONSOLE_OUTPUT
+#define DEBUG(...) { pc.printf(__VA_ARGS__); }
+#else
+#define DEBUG(...)
+#endif
+
+BLE  		ble_rcb;
+Serial      pc(USBTX, USBRX);
+
+uint8_t RCBControllerPayload[10] = {0,};
+RCBController 		controller;
+
+// RCBController Service
+static const uint16_t RCBController_service_uuid = 0xFFF0;
+static const uint16_t RCBController_Characteristic_uuid = 0xFFF1;
+const char *deviceName = "Mbed-BLE";
+char *const opngmsg =
+    "\x1b[2J\x1b[H"__FILE__ "\r\n"__DATE__ " " __TIME__ " (UTC)\r\n""\r\n";
+
+GattCharacteristic  ControllerChar (
+    RCBController_Characteristic_uuid,RCBControllerPayload,10, 10,
+    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE |
+    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE
+);
+GattCharacteristic *ControllerChars[] = {&ControllerChar};
+GattService         RCBControllerService(
+    RCBController_service_uuid,
+    ControllerChars,
+    sizeof(ControllerChars) / sizeof(GattCharacteristic *)
+);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+void data_analysis(void)
+{
+    static uint8_t cont_flg_A = 0;
+    static uint8_t cont_flg_B = 0;
+    static uint8_t cont_flg_X = 0;
+    static uint8_t cont_flg_Y = 0;
+
+    if (controller.status.A == 1) {
+        if (cont_flg_A == 0) {
+            cont_flg_A = 1;
+        }
+    } else {
+        cont_flg_A = 0;
+    }
+    if (controller.status.B == 1) {
+        if (cont_flg_B == 0) {
+            cont_flg_B = 1;
+        }
+    } else {
+        cont_flg_B = 0;
+    }
+    if (controller.status.X == 1) {
+        if (cont_flg_X == 0) {
+            cont_flg_X = 1;
+        }
+    } else {
+        cont_flg_X = 0;
+    }
+    if (controller.status.Y == 1) {
+        if (cont_flg_Y == 0) {
+            cont_flg_Y = 1;
+        }
+    } else {
+        cont_flg_Y = 0;
+    }
+}
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
+{
+    DEBUG("Disconnected!\r\n");
+    DEBUG("Restarting the advertising process\r\n");
+    ble_rcb.startAdvertising();
+}
+
+void onDataWritten(const GattWriteCallbackParams *params)
+{
+    if (params->handle == ControllerChar.getValueAttribute().getHandle()) {
+        uint16_t bytesRead;
+        ble_rcb.readCharacteristicValue(
+            ControllerChar.getValueAttribute().getHandle(),
+            RCBControllerPayload, &bytesRead
+        );
+        memcpy( &controller.data[0], RCBControllerPayload, sizeof(controller));
+        DEBUG("DATA:0x%02x 0x%02x %d %d %d %d %d %d %d 0x%02x\r\n",
+              controller.data[0],controller.data[1],
+              controller.data[2],controller.data[3],
+              controller.data[4],controller.data[5],
+              controller.data[6],controller.data[7],
+              controller.data[8],controller.data[9]
+             );
+        data_analysis();
+    }
+}
+
+int main(void)
+{
+    DEBUG(opngmsg);
+    DEBUG("\r\nInitialising the nRF51822\r\n");
+    // Check TYBLE-16 configuration
+    cpu_sys();
+    compile_condition();
+
+    ble_rcb.init();
+    ble_rcb.setDeviceName((const uint8_t *)deviceName);
+    ble_rcb.onDisconnection(disconnectionCallback);
+    ble_rcb.onDataWritten(onDataWritten);
+    DEBUG("Start RCB Controller\r\n");
+    /* setup advertising */
+    ble_rcb.accumulateAdvertisingPayload(
+        GapAdvertisingData::BREDR_NOT_SUPPORTED
+    );
+    ble_rcb.setAdvertisingType(
+        GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED
+    );
+    ble_rcb.accumulateAdvertisingPayload(
+        GapAdvertisingData::SHORTENED_LOCAL_NAME,
+        (const uint8_t *)deviceName, strlen(deviceName)
+    );
+    ble_rcb.accumulateAdvertisingPayload(
+        GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
+        (const uint8_t *)RCBController_service_uuid,
+        sizeof(RCBController_service_uuid)
+    );
+    ble_rcb.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
+    ble_rcb.startAdvertising();
+    ble_rcb.addService(RCBControllerService);
+    while (true) {
+        ble_rcb.waitForEvent();
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/5_SDCard/FatFs_Mon/mon.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,1228 @@
+/*
+ * mbed Application program for the mbed
+ *  FatFs Check program / monitor part
+ *
+ * Copyright (c) 2015,'18 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    May        5th, 2015
+ *      Revised:    June      14th, 2015
+ *      Revised:    April      7th, 2018
+ */
+
+/*
+ *---------------- REFERENCE ---------------------------------------------------
+ * Original Source Information
+ * FatFs sample program
+ *      ChaN FatFs  http://elm-chan.org/
+ *      http://elm-chan.org/fsw/ff/00index_e.html
+ */
+/*----------------------------------------------------------------------*/
+/* FAT file system sample project for FatFs            (C)ChaN, 2016    */
+/*----------------------------------------------------------------------*/
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#if (MBED_MAJOR_VERSION == 2)
+#include "SDFileSystem.h"
+#elif (MBED_MAJOR_VERSION == 5)
+#include "FATFileSystem.h"
+#endif
+#include "ff.h"
+#include "ffconf.h"
+#include "diskio.h"
+#include "mon.h"
+
+//  Definition -----------------------------------------------------------------
+#define DO_DEBUG    0
+
+#if DO_DEBUG
+#define DEBUG_LINE  pc.printf("line:%d\r\n", __LINE__);
+#else
+#define DEBUG_LINE  {;}
+#endif
+
+// Com
+#if  1
+#define BAUD(x)     pc.baud(x)
+#define GETC(x)     pc.getc(x)
+#define PUTC(x)     pc.putc(x)
+#define PUTS(x)     pc.puts(x)
+#define PRINTF(...) pc.printf(__VA_ARGS__)
+#define READABLE(x) pc.readable(x)
+#else
+#define BAUD(x)     {;}
+#define GETC(x)     {;}
+#define PUTC(x)     {;}
+#define PRINTF(...) {;}
+#define READABLE(x) {;}
+#endif
+
+#define UTC_JST_OFFSET  (32400) // +9 hours
+
+// from ffconf.h
+#define _VOLUMES    1
+#define FF_USE_LFN  0
+
+#if !defined(FF_FS_RPATH)
+#define FF_FS_RPATH 0
+#endif
+
+#define DW_CHAR         sizeof(char)
+#define DW_SHORT        sizeof(short)
+#define DW_LONG         sizeof(long)
+
+/* These types must be 16-bit, 32-bit or larger integer */
+typedef int             INT;
+typedef unsigned int    UINT;
+
+/* These types must be 8-bit integer */
+typedef char            CHAR;
+typedef unsigned char   UCHAR;
+typedef unsigned char   BYTE;
+
+/* These types must be 16-bit integer */
+typedef short           SHORT;
+typedef unsigned short  USHORT;
+typedef unsigned short  WORD;
+typedef unsigned short  WCHAR;
+
+/* These types must be 32-bit integer */
+typedef long            LONG;
+typedef unsigned long   ULONG;
+typedef unsigned long   DWORD;
+/*  by Kenji Arai / JH1PJL  September 10th, 2012  */
+typedef unsigned long long  DDWORD;
+
+//  RAM ------------------------------------------------------------------------
+BYTE Buff[4096];
+char Linebuf[128];          // Console input buffer
+FATFS Fatfs[_VOLUMES];      // File system object for each logical drive
+FIL File1, File2;           // File objects
+FATFS_DIR* Dirx;
+FILINFO Finfo;
+#if FF_USE_LFN
+//inside of FILINFO
+char Lfname[512];
+#endif
+DWORD AccSize;              // Work register for fs command
+WORD AccFiles, AccDirs;
+
+//  ROM / Constant data --------------------------------------------------------
+char *const monmsg0 = "Start monitor program for FatFs File System\r\n";
+char *const monmsg1 = " <Please press any key to start the monitor>";
+
+static const char HelpMsg0[] =
+    "dir   <full_pass>\r\n"
+    "type  <file_name>\r\n"
+    "vol\r\n"
+    "ren   <org_file_name> <new_file_name>\r\n"
+    "copy  <file_name> <file_name>\r\n"
+    "mkdir <dir_name>\r\n"
+    "cd    <dir_name>\r\n"
+    "x     extend commands mode\r\n"
+    "q     Return to main\r\n"
+    "t     Show current time or Adjust time\r\n"
+    "      e.g. t 18 3 28 14 48 20 -> 2018-03-28 14:48:20\r\n"
+    "?     Help/You know the command\r\n"
+    "\r\n";
+
+static const char HelpMsg1[] =
+    "[File system controls]\r\n"
+    " fi <ld#> [<mount>]- Force initialized the volume\r\n"
+    " fs [<path>] - Show volume status\r\n"
+    " fl [<path>] - Show a directory\r\n"
+    " fo <mode> <file> - Open a file\r\n"
+    "    <mode>  Read=1, Write=2\r\n"
+    " fc - Close the file\r\n"
+    " fe <ofs> - Move fp in normal seek\r\n"
+    " fd <len> - Read and dump the file\r\n"
+    " fr <len> - Read the file\r\n"
+    " fw <len> <val> - Write to the file\r\n"
+    " fn <org.name> <new.name> - Rename an object\r\n"
+    " fu <name> - Unlink an object\r\n"
+    " fv - Truncate the file at current fp\r\n"
+    " fk <name> - Create a directory\r\n"
+    " fa <atrr> <mask> <object name> - Change attribute of an object\r\n"
+    " ft <year> <month> <day> <hour> <min> <sec> <name>"
+    " - Change timestamp of an object\r\n"
+    " fx <src.file> <dst.file> - Copy a file\r\n"
+    " fg <path> - Change current directory\r\n"
+    " fq - Show current directory\r\n"
+    " fb <name> - Set volume label\r\n"
+    " fm <ld#> <type> <csize> - Create file system\r\n"
+    " fz [<len>] - Change/Show R/W length for fr/fw/fx command\r\n"
+    "[Disk contorls]\r\n"
+    " di <pd#> - Initialize disk\r\n"
+    " dd [<pd#> <lba>] - Dump a secrtor\r\n"
+    " ds <pd#> - Show disk status\r\n"
+    "[Buffer controls]\r\n"
+    " bd <ofs> - Dump working buffer\r\n"
+    " be <ofs> [<data>] ... - Edit working buffer\r\n"
+    " br <pd#> <lba> [<count>] - Read disk into working buffer\r\n"
+    " bw <pd#> <lba> [<count>] - Write working buffer into disk\r\n"
+    " bf <val> - Fill working buffer\r\n"
+    "[Misc commands]\r\n"
+    " q Return\r\n"
+    " ? Help\r\n"
+    "\r\n";
+
+//  Function prototypes --------------------------------------------------------
+#if (MBED_MAJOR_VERSION == 2)
+extern SDFileSystem fs;
+#elif (MBED_MAJOR_VERSION == 5)
+extern HeapBlockDevice bd;
+extern FATFileSystem fs;
+#endif
+
+static void extended_mon( char *ptr );
+static void v_next( char *ptr );
+static void d_next( char *ptr );
+static void c_next( char *ptr );
+static void m_next( char *ptr );
+static void r_next( char *ptr );
+static void t_next( char *ptr );
+static void memory_inf(char *ptr);
+static void disk_inf(char *ptr);
+
+static void crlf( void );
+static FRESULT scan_files( char* path );
+static void put_rc( FRESULT rc );
+static void file_inf( char *ptr );
+static void put_dump( void* buff, unsigned long addr, int len, int width );
+static void chk_and_set_time(char *ptr);
+static int xatoi ( char **str, long *res );
+
+void get_line (char *buff, int len);
+
+//  Object ---------------------------------------------------------------------
+extern  Serial pc;
+static Timer   t;
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+// Monitor program for File control
+void mon ()
+{
+    char *ptr;
+
+    Dirx = new FATFS_DIR;
+    /* Open Uart to communicate with Host PC */
+    PUTS(monmsg0);
+    PUTS(monmsg1);
+    crlf();
+#if FF_USE_LFN
+    // no needs because FILINFO structure is changed
+    Finfo.lfname = Lfname;
+    Finfo.lfsize = sizeof Lfname;
+#endif
+    for (;;) {
+        DEBUG_LINE
+        PUTC('>');
+        ptr = Linebuf;
+        get_line( ptr, sizeof(Linebuf) );
+        switch ( *ptr++ ) {
+                // vol
+            case 'v' :
+                v_next(ptr);
+                break;
+                // dir
+            case 'd' :
+                d_next(ptr);
+                break;
+                // cd, copy
+            case 'c' :
+                c_next(ptr);
+                break;
+                // mkdir
+            case 'm' :
+                m_next(ptr);
+                break;
+                // ren
+            case 'r' :
+                r_next(ptr);
+                break;
+            case 't' :
+                t_next(ptr);
+                break;
+            case 'x' :
+                extended_mon(ptr);
+                break;
+                // Help
+            case '?' :
+                PUTS(HelpMsg0);
+                break;
+                // Exit monitor (return to main())
+            case 'q' :
+                PUTS("Return to main\r\n");
+                return;
+                // Not a command
+            default:
+                PUTS("? [HELP]=?");
+                crlf();
+                break;
+        }
+    }
+}
+
+uint32_t get_disk_freespace(void)
+{
+    long  p1;
+    UINT   s1, s2;
+    FATFS  *fs;
+    BYTE res;
+
+    if (Dirx == NULL){
+        Dirx = new FATFS_DIR;
+    }
+    char p = NULL;
+    res = f_opendir(Dirx, &p);
+    if (res) {
+        return 0;
+    }
+    p1 = s1 = s2 = 0;
+    for(;;) {
+        res = f_readdir(Dirx, &Finfo);
+        if ((res != FR_OK) || !Finfo.fname[0]) break;
+        if (Finfo.fattrib & AM_DIR) {
+            s2++;
+        } else {
+            s1++;
+            p1 += Finfo.fsize;
+        }
+    }
+    res = f_getfree(&p, (DWORD*)&p1, &fs);
+    uint32_t size = p1 * fs->csize * 512;
+    if (res == FR_OK) {
+        return size;
+    } else {
+        return 0;
+    }
+}
+
+static void extended_mon( char *ptr )
+{
+    PUTS(HelpMsg1);
+    while(true) {
+        PUTS("e>");
+        ptr = Linebuf;
+        get_line( ptr, sizeof(Linebuf) );
+        switch ( *ptr++ ) {
+            case 'f' :
+                DEBUG_LINE;
+                file_inf(ptr);
+                break;
+            case 'd' :
+                DEBUG_LINE;
+                disk_inf(ptr);
+                break;
+            case 'm' :
+                DEBUG_LINE;
+                memory_inf(ptr);
+                break;
+            case '?' :
+                DEBUG_LINE;
+                PUTS(HelpMsg1);
+                break;
+            case 'q' :
+                DEBUG_LINE;
+                return;
+            default:
+                PUTS( "?\r\n" );
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+// General monitor functions
+static void v_next( char *ptr )
+{
+    switch ( *ptr++ ) {
+        case 'o' :
+            if (*ptr == 'l') {
+                *ptr = 's';
+                file_inf(ptr);  // fs [<path>] - Show volume status
+            }
+            break;
+        default:
+            PUTS( "?\r\n" );
+    }
+}
+
+static void d_next(char *ptr)
+{
+    switch ( *ptr++ ) {
+        case 'i' :
+            if (*ptr == 'r') {
+                *ptr = 'l';
+                file_inf(ptr);  // fl [<path>] - Directory listing
+            }
+            break;
+        default:
+            PUTS( "?\r\n" );
+    }
+}
+
+static void c_next(char *ptr)
+{
+    switch ( *ptr++ ) {
+        case 'o' :
+            if ((*ptr == 'p') && (*(ptr + 1) == 'y')) {
+                ptr++;
+                *ptr = 'x';
+                file_inf(ptr);  // fx <src_name> <dst_name> - Copy file
+            }
+            break;
+        case 'd' :
+            *ptr = 'g';
+            file_inf(ptr);  // fx <src_name> <dst_name> - Copy file
+            break;
+        default:
+            PUTS( "?\r\n" );
+    }
+}
+
+static void m_next(char *ptr)
+{
+    switch ( *ptr++ ) {
+        case 'k' :
+            if ((*ptr == 'd') && (*(ptr + 1) == 'i') && (*(ptr + 2) == 'r')) {
+                ptr += 2;
+                *ptr = 'k';
+                file_inf(ptr);  // fk <name> - Create a directory
+            }
+            break;
+        default:
+            PUTS("?\r\n");
+    }
+}
+
+static void r_next(char *ptr)
+{
+    switch (*ptr++) {
+        case 'e' :
+            if (*ptr == 'n') {
+                // fn <old_name> <new_name> - Change file/dir name
+                file_inf(ptr);
+            }
+            break;
+        default:
+            PUTS("?\r\n");
+    }
+}
+
+static void t_next(char *ptr)
+{
+    switch (*ptr++) {
+        case ' ' :
+        case 0x0d:
+            chk_and_set_time(ptr);
+        case 'y' :
+            if ((*ptr == 'p') && (*(ptr + 1) == 'e')) {
+                ptr++;
+                *ptr = '&';
+                file_inf(ptr);
+            }
+            break;
+        default:
+            PUTS("?\r\n");
+    }
+}
+
+static FRESULT scan_files (
+    char* path      /* Pointer to the path name working buffer */
+)
+{
+    FATFS_DIR  dirs;
+    FRESULT res;
+    BYTE i;
+    char *fn;
+
+    if ((res = f_opendir(&dirs, path)) == FR_OK) {
+        i = strlen(path);
+        PRINTF("path: %s, n=%u\r\n", path, i);
+        while (((res = f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) {
+            if (FF_FS_RPATH && Finfo.fname[0] == '.') {
+                continue;
+            }
+#if FF_USE_LFN
+            //fn = *Finfo.lfname ? Finfo.lfname : Finfo.fname;
+            if (Finfo.altname[0] == 0) {
+                fn = Finfo.fname;
+            } else {
+                fn = Finfo.altname;
+            }
+#else
+            fn = Finfo.fname;
+#endif
+            if (Finfo.fattrib & AM_DIR) {
+                AccDirs++;
+                *(path+i) = '/';
+                strcpy(path+i+1, fn);
+                res = scan_files(path);
+                *(path+i) = '\0';
+                if (res != FR_OK) break;
+            } else {
+                PRINTF("%s/%s\r\n", path, fn);
+                AccFiles++;
+                AccSize += Finfo.fsize;
+            }
+        }
+    }
+    return res;
+}
+
+static void put_rc (FRESULT rc)
+{
+    const char *str =
+        "OK\0" "DISK_ERR\0" "INT_ERR\0" "NOT_READY\0" "NO_FILE\0" "NO_PATH\0"
+        "INVALID_NAME\0" "DENIED\0" "EXIST\0" "INVALID_OBJECT\0"
+        "WRITE_PROTECTED\0" "INVALID_DRIVE\0" "NOT_ENABLED\0"
+        "NO_FILE_SYSTEM\0" "MKFS_ABORTED\0" "TIMEOUT\0"
+        "LOCKED\0" "NOT_ENOUGH_CORE\0" "TOO_MANY_OPEN_FILES\0";
+    int i;
+
+    for ( i = 0; i != rc && *str; i++ ) {
+        while ( *str++ ) {
+            ;
+        }
+    }
+    PRINTF( "rc=%u FR_%s\r\n", (UINT)rc, str );
+}
+
+static void file_inf(char *ptr)
+{
+    long  p1, p2, p3;
+    CHAR   *ptr2;
+    BYTE   f_res;
+    UINT   s1, s2, cnt, blen = sizeof Buff;
+    FATFS  *fs;
+    static const BYTE ft[] = {0, 12, 16, 32};
+    BYTE res;
+    DWORD ofs = 0;
+    uint32_t tim;
+
+    switch (*ptr++) {
+        case '&' :
+            DEBUG_LINE;
+            while (*ptr == ' ') ptr++;
+            /* Open a file */
+            f_res = f_open(&File1, ptr, FA_READ);
+            if ( f_res ) {
+                put_rc((FRESULT)f_res);
+                break;
+            }
+            DEBUG_LINE;
+            /* Read all lines and display it */
+            while(true) {
+                f_res = f_read(&File1, (TCHAR*)Buff, blen, &cnt);
+                if ( f_res ) {
+                    put_rc((FRESULT)f_res);
+                    break;
+                }
+                for (s1 = 0; s1 < cnt; s1++) {
+                    PUTC(Buff[s1]);
+                }
+                if (cnt != blen) {
+                    break;
+                }
+            }
+            DEBUG_LINE;
+            /* Close the file */
+            f_close(&File1);
+            break;
+
+        case 'i' :  /* fi [<opt>]- Initialize logical drive */
+            if ( !xatoi(&ptr, &p1) ) {
+                break;
+            }
+            if (!xatoi(&ptr, &p2)) p2 = 0;
+            put_rc(f_mount(&Fatfs[p1], (const TCHAR*)p1, 0));
+            break;
+
+        case 's' :  /* fs [<path>] - Show volume status */
+            f_res = f_getfree( ptr, (DWORD*)&p2, &fs );
+            if ( f_res ) {
+                put_rc((FRESULT)f_res);
+                break;
+            }
+            PRINTF
+            (
+                "\rFAT type = FAT%u\r\nBytes/Cluster"
+                " = %lu\r\nNumber of FATs = %u\r\n"
+                "Root DIR entries = %u\r\n"
+                "Sectors/FAT = %lu\r\n"
+                "Number of clusters = %lu\r\n"
+                "FAT start (lba) = %lu\r\n"
+                "DIR start (lba,clustor) = %lu\r\n"
+                "Data start (lba) = %lu\r\n",
+                ft[fs->fs_type & 3], (DWORD)fs->csize * 512, fs->n_fats,
+                fs->n_rootdir, fs->fsize, (DWORD)fs->n_fatent - 2,
+                fs->fatbase, fs->dirbase, fs->database
+            );
+            AccSize = AccFiles = AccDirs = 0;
+            break;
+        case 'l' :  /* fl [<path>] - Directory listing */
+            while (*ptr == ' ') ptr++;
+            res = f_opendir(Dirx, ptr);
+            if (res) {
+                put_rc((FRESULT)res);
+                break;
+            }
+            p1 = s1 = s2 = 0;
+            for(;;) {
+                res = f_readdir(Dirx, &Finfo);
+                if ((res != FR_OK) || !Finfo.fname[0]) break;
+                if (Finfo.fattrib & AM_DIR) {
+                    s2++;
+                } else {
+                    s1++;
+                    p1 += Finfo.fsize;
+                }
+                PRINTF("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu  %s\r\n",
+                       (Finfo.fattrib & AM_DIR) ? 'D' : '-',
+                       (Finfo.fattrib & AM_RDO) ? 'R' : '-',
+                       (Finfo.fattrib & AM_HID) ? 'H' : '-',
+                       (Finfo.fattrib & AM_SYS) ? 'S' : '-',
+                       (Finfo.fattrib & AM_ARC) ? 'A' : '-',
+                       (Finfo.fdate >> 9) + 1980, (Finfo.fdate >> 5) & 15,
+                       Finfo.fdate & 31,
+                       (Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63,
+                       Finfo.fsize, Finfo.fname);
+            }
+#if 0   // f_getfree cannnot count under Dir, subdirectory area
+            PRINTF("%4u File(s),%10lu bytes total\r\n%4u Dir(s)", s1, p1, s2);
+            res = f_getfree(ptr, (DWORD*)&p1, &fs);
+            if (res == FR_OK)
+                PRINTF(", %10lu bytes free\r\n", p1 * fs->csize * 512);
+            else
+                put_rc((FRESULT)res);
+#else
+            PRINTF("%4u File(s) = %10lu bytes total, %4u Dir(s)\r\n",
+                   s1, p1, s2);
+#endif
+            break;
+
+        case 'o' :  /* fo <mode> <file> - Open a file */
+            if (!xatoi(&ptr, &p1)) break;
+            while (*ptr == ' ') ptr++;
+            put_rc(f_open(&File1, ptr, (BYTE)p1));
+#if 0
+            put_rc(f_open(&File1, "savedata.txt", 1));
+            PRINTF("Open savedata.txt as read mode\r\n");
+#endif
+            break;
+
+        case 'c' :  /* fc - Close a file */
+            put_rc(f_close(&File1));
+            break;
+
+        case 'e' :  /* fe - Seek file pointer */
+            if (!xatoi(&ptr, &p1)) break;
+            res = f_lseek(&File1, p1);
+            put_rc((FRESULT)res);
+            if (res == FR_OK)
+                PRINTF("fptr=%lu(0x%lX)\r\n", File1.fptr, File1.fptr);
+            break;
+
+        case 'd' :  /* fd <len> - read and dump file from current fp */
+            if (!xatoi(&ptr, &p1)) break;
+            ofs = File1.fptr;
+            while (p1) {
+                if ((UINT)p1 >= 16) {
+                    cnt = 16;
+                    p1 -= 16;
+                } else                {
+                    cnt = p1;
+                    p1 = 0;
+                }
+                res = f_read(&File1, Buff, cnt, &cnt);
+                if (res != FR_OK) {
+                    put_rc((FRESULT)res);
+                    break;
+                }
+                if (!cnt) break;
+                put_dump(Buff, ofs, cnt, DW_CHAR);
+                ofs += 16;
+            }
+            break;
+
+        case 'r' :  /* fr <len> - read file */
+            if (!xatoi(&ptr, &p1)) break;
+            p2 = 0;
+            t.reset();
+            t.start();
+            while (p1) {
+                if ((UINT)p1 >= blen) {
+                    cnt = blen;
+                    p1 -= blen;
+                } else {
+                    cnt = p1;
+                    p1 = 0;
+                }
+                res = f_read(&File1, Buff, cnt, &s2);
+                if (res != FR_OK) {
+                    put_rc((FRESULT)res);
+                    break;
+                }
+                p2 += s2;
+                if (cnt != s2) break;
+            }
+            tim = t.read_ms();
+            PRINTF("%lu bytes read with %lu kB/sec.\r\n",
+                   p2, tim ? (p2 / tim) : 0);
+            break;
+
+        case 'w' :  /* fw <len> <val> - write file */
+            if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break;
+            memset(Buff, (BYTE)p2, blen);
+            p2 = 0;
+            t.reset();
+            t.start();
+            while (p1) {
+                if ((UINT)p1 >= blen) {
+                    cnt = blen;
+                    p1 -= blen;
+                } else {
+                    cnt = p1;
+                    p1 = 0;
+                }
+                res = f_write(&File1, Buff, cnt, &s2);
+                if (res != FR_OK) {
+                    put_rc((FRESULT)res);
+                    break;
+                }
+                p2 += s2;
+                if (cnt != s2) break;
+            }
+            tim = t.read_ms();
+            PRINTF("%lu bytes written with %lu kB/sec.\r\n",
+                   p2, tim ? (p2 / tim) : 0);
+            break;
+
+        case 'n' :  /* fn <org.name> <new.name> - Change name of an object */
+            while (*ptr == ' ') ptr++;
+            ptr2 = strchr(ptr, ' ');
+            if (!ptr2) break;
+            *ptr2++ = 0;
+            while (*ptr2 == ' ') ptr2++;
+            put_rc(f_rename(ptr, ptr2));
+            break;
+
+        case 'u' :  /* fu <name> - Unlink an object */
+            while (*ptr == ' ') ptr++;
+            put_rc(f_unlink(ptr));
+            break;
+
+        case 'v' :  /* fv - Truncate file */
+            put_rc(f_truncate(&File1));
+            break;
+
+        case 'k' :  /* fk <name> - Create a directory */
+            while (*ptr == ' ') ptr++;
+            put_rc(f_mkdir(ptr));
+            break;
+#if 0
+        case 'a' :  /* fa <atrr> <mask> <name> - Change attribute of an object */
+            if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break;
+            while (*ptr == ' ') ptr++;
+            put_rc(f_chmod(ptr, p1, p2));
+            break;
+#endif
+#if 0
+            /* ft <year> <month> <day> <hour> <min> <sec> <name>
+                                                 - Change timestamp of an object */
+        case 't' :
+            if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) {
+                break;
+            }
+            Finfo.fdate = ((p1 - 1980) << 9) | ((p2 & 15) << 5) | (p3 & 31);
+            if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) {
+                break;
+            }
+            Finfo.ftime =
+                ((p1 & 31) << 11) | ((p2 & 63) << 5) | ((p3 >> 1) & 31);
+            put_rc(f_utime(ptr, &Finfo));
+            break;
+#endif
+#if FILCPY_NOTUSE == 0
+        case 'x' : /* fx <src_name> <dst_name> - Copy file */
+            while ( *ptr == ' ' ) {
+                ptr++;
+            }
+            ptr2 = strchr( ptr, ' ' );
+            if ( !ptr2 ) {
+                break;
+            }
+            *ptr2++ = 0;
+            while ( *ptr2 == ' ' ) {
+                ptr2++;
+            }
+            f_res = f_open( &File1, ptr, FA_OPEN_EXISTING | FA_READ );
+            PRINTF("Opening %s \r\n", ptr);
+            if ( f_res ) {
+                put_rc( (FRESULT)f_res );
+                break;
+            }
+            f_res = f_open( &File2, ptr2, FA_CREATE_ALWAYS | FA_WRITE );
+            PRINTF(" Creating %s \r\n", ptr2);
+            if ( f_res ) {
+                put_rc( (FRESULT)f_res );
+                f_close( &File1 );
+                break;
+            }
+            PRINTF("Copying file...");
+            p1 = 0;
+            for ( ;; ) {
+                f_res = f_read( &File1, Buff, blen, &s1 );
+                if ( f_res || s1 == 0 ) {
+                    break;   /* error or eof */
+                }
+                f_res = f_write( &File2, Buff, s1, &s2 );
+                p1 += s2;
+                if ( f_res || s2 < s1 ) {
+                    break;   /* error or disk full */
+                }
+            }
+            f_close( &File1 );
+            f_close( &File2 );
+            crlf();
+            break;
+#endif
+#if 0
+        case 'x' : /* fx <src.name> <dst.name> - Copy a file */
+            while (*ptr == ' ') ptr++;
+            ptr2 = strchr(ptr, ' ');
+            if (!ptr2) break;
+            *ptr2++ = 0;
+            while (*ptr2 == ' ') ptr2++;
+            PRINTF("Opening \"%s\"", ptr);
+            res = f_open(&File1, ptr, FA_OPEN_EXISTING | FA_READ);
+            PUTS("\r\n");
+            if (res) {
+                put_rc((FRESULT)res);
+                break;
+            }
+            PRINTF("Creating \"%s\"", ptr2);
+            res = f_open(&File1, ptr2, FA_CREATE_ALWAYS | FA_WRITE);
+            PUTS("\r\n");
+            if (res) {
+                put_rc((FRESULT)res);
+                f_close(&File1);
+                break;
+            }
+            PRINTF("Copying file...");
+            t.reset();
+            t.start();
+            p1 = 0;
+            for (;;) {
+                res = f_read(&File1, Buff, blen, &s1);
+                if (res || s1 == 0) break;   /* error or eof */
+                res = f_write(&File2, Buff, s1, &s2);
+                p1 += s2;
+                if (res || s2 < s1) break;   /* error or disk full */
+            }
+            tim = t.read_ms();
+            PRINTF("\r\n%lu bytes copied with %lu kB/sec.\r\n",
+                   p1, tim ? (p1 / tim) : 0);
+            f_close(&File1);
+            f_close(&File2);
+            break;
+#endif
+#if FF_FS_RPATH
+        case 'g' :  /* fg <path> - Change current directory */
+            while (*ptr == ' ') ptr++;
+            put_rc(f_chdir(ptr));
+            break;
+#if FF_FS_RPATH >= 2
+        case 'q' :  /* fq - Show current dir path */
+            res = f_getcwd(Linebuf, sizeof Linebuf);
+            if (res)
+                put_rc(res);
+            else
+                PRINTF("%s\r\n", Linebuf);
+            break;
+#endif
+#endif
+#if FF_USE_LABEL
+        case 'b' :  /* fb <name> - Set volume label */
+            while (*ptr == ' ') ptr++;
+            put_rc(f_setlabel(ptr));
+            break;
+#endif  /* FF_USE_LABEL */
+#if FF_USE_MKFS
+        case 'm' :  /* fm <type> <csize> - Create file system */
+            if (!xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break;
+            PRINTF("The volume will be formatted. Are you sure? (Y/n)=");
+            get_line(Linebuf, sizeof Linebuf);
+            if (Linebuf[0] == 'Y')
+                put_rc(f_mkfs("", (BYTE)p2, (DWORD)p3, Buff, sizeof Buff));
+            break;
+#endif  /* FF_USE_MKFS */
+            /* fz [<size>] - Change/Show R/W length for fr/fw/fx command */
+        case 'z' :
+            if (xatoi(&ptr, &p1) && p1 >= 1 && p1 <= (long)sizeof Buff)
+                blen = p1;
+            PRINTF("blen=%u\r\n", blen);
+            break;
+    }
+}
+
+static void memory_inf(char *ptr)
+{
+    long  p1, p2, p3;
+
+    switch (*ptr++) {
+        case 'd' :  /* md[b|h|w] <address> [<count>] - Dump memory */
+            switch (*ptr++) {
+                case 'w':
+                    p3 = DW_LONG;
+                    break;
+                case 'h':
+                    p3 = DW_SHORT;
+                    break;
+                default:
+                    p3 = DW_CHAR;
+            }
+            if (!xatoi(&ptr, &p1)) break;
+            if (!xatoi(&ptr, &p2)) p2 = 128 / p3;
+            for (ptr = (char*)p1; p2 >= 16 / p3; ptr += 16, p2 -= 16 / p3)
+                put_dump(ptr, (DWORD)ptr, 16 / p3, p3);
+            if (p2) put_dump((BYTE*)ptr, (UINT)ptr, p2, p3);
+            break;
+        case 'f' :  /* mf <address> <value> <count> - Fill memory */
+            if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) {
+                break;
+            }
+            while (p3--) {
+                *(BYTE*)p1 = (BYTE)p2;
+                p1++;
+            }
+            break;
+        case 'e' :  /* me[b|h|w] <address> [<value> ...] - Edit memory */
+            switch (*ptr++) {   /* Get data width */
+                case 'w':
+                    p3 = DW_LONG;
+                    break;
+                case 'h':
+                    p3 = DW_SHORT;
+                    break;
+                default:
+                    p3 = DW_CHAR;
+            }
+            if (!xatoi(&ptr, &p1)) break;   /* Get start address */
+            if (xatoi(&ptr, &p2)) { /* 2nd parameter is given (direct mode) */
+                do {
+                    switch (p3) {
+                        case DW_LONG:
+                            *(DWORD*)p1 = (DWORD)p2;
+                            break;
+                        case DW_SHORT:
+                            *(WORD*)p1 = (WORD)p2;
+                            break;
+                        default:
+                            *(BYTE*)p1 = (BYTE)p2;
+                    }
+                    p1 += p3;
+                } while (xatoi(&ptr, &p2)); /* Get next value */
+                break;
+            }
+            for (;;) {  /* 2nd parameter is not given (interactive mode) */
+                switch (p3) {
+                    case DW_LONG:
+                        PRINTF("%08X 0x%08X-", p1, *(DWORD*)p1);
+                        break;
+                    case DW_SHORT:
+                        PRINTF("%08X 0x%04X-", p1, *(WORD*)p1);
+                        break;
+                    default:
+                        PRINTF("%08X 0x%02X-", p1, *(BYTE*)p1);
+                }
+                ptr = Linebuf;
+                get_line(ptr, sizeof Linebuf);
+                if (*ptr == '.') break;
+                if ((BYTE)*ptr >= ' ') {
+                    if (!xatoi(&ptr, &p2)) continue;
+                    switch (p3) {
+                        case DW_LONG:
+                            *(DWORD*)p1 = (DWORD)p2;
+                            break;
+                        case DW_SHORT:
+                            *(WORD*)p1 = (WORD)p2;
+                            break;
+                        default:
+                            *(BYTE*)p1 = (BYTE)p2;
+                    }
+                }
+                p1 += p3;
+            }
+    }
+}
+
+static void disk_inf(char *ptr)
+{
+    long  p1, p2;
+    UINT   s1;
+    BYTE res, b, drv = 0;
+    DWORD ofs = 0, sect = 0, blk[2];
+
+    switch (*ptr++) {
+        case 'd' :  /* dd [<pd#> <sect>] - Dump secrtor */
+            if (!xatoi(&ptr, &p1)) {
+                p1 = drv;
+                p2 = sect;
+            } else {
+                if (!xatoi(&ptr, &p2)) break;
+            }
+            drv = (BYTE)p1;
+            sect = p2;
+            res = disk_read(drv, Buff, sect, 1);
+            if (res) {
+                PRINTF("rc=%d\r\n", (WORD)res);
+                break;
+            }
+            PRINTF("PD#:%u LBA:%lu\r\n", drv, sect++);
+            for (ptr=(char*)Buff, ofs = 0; ofs < 0x200; ptr += 16, ofs += 16)
+                put_dump((BYTE*)ptr, ofs, 16, DW_CHAR);
+            break;
+
+        case 'i' :  /* di <pd#> - Initialize disk */
+            if (!xatoi(&ptr, &p1)) break;
+            PRINTF("rc=%d\r\n", (WORD)disk_initialize((BYTE)p1));
+            break;
+
+        case 's' :  /* ds <pd#> - Show disk status */
+            if (!xatoi(&ptr, &p1)) break;
+            if (disk_ioctl((BYTE)p1, GET_SECTOR_COUNT, &p2) == RES_OK) {
+                PRINTF("Drive size: %lu sectors\r\n", p2);
+            }
+            if (disk_ioctl((BYTE)p1, GET_BLOCK_SIZE, &p2) == RES_OK) {
+                PRINTF("Block size: %lu sectors\r\n", p2);
+            }
+            if (disk_ioctl((BYTE)p1, MMC_GET_TYPE, &b) == RES_OK) {
+                PRINTF("Media type: %u\r\n", b);
+            }
+            if (disk_ioctl((BYTE)p1, MMC_GET_CSD, Buff) == RES_OK) {
+                PUTS("CSD:\r\n");
+                put_dump(Buff, 0, 16, DW_CHAR);
+            }
+            if (disk_ioctl((BYTE)p1, MMC_GET_CID, Buff) == RES_OK) {
+                PUTS("CID:\r\n");
+                put_dump(Buff, 0, 16, DW_CHAR);
+            }
+            if (disk_ioctl((BYTE)p1, MMC_GET_OCR, Buff) == RES_OK) {
+                PUTS("OCR:\r\n");
+                put_dump(Buff, 0, 4, DW_CHAR);
+            }
+            if (disk_ioctl((BYTE)p1, MMC_GET_SDSTAT, Buff) == RES_OK) {
+                PUTS("SD Status:\r\n");
+                for (s1 = 0; s1 < 64; s1 += 16) {
+                    put_dump(Buff+s1, s1, 16, DW_CHAR);
+                }
+            }
+            break;
+
+        case 'c' :  /* Disk ioctl */
+            switch (*ptr++) {
+                case 's' :  /* dcs <pd#> - CTRL_SYNC */
+                    if (!xatoi(&ptr, &p1)) break;
+                    PRINTF("rc=%d\r\n", disk_ioctl((BYTE)p1, CTRL_SYNC, 0));
+                    break;
+                case 'e' :  /* dce <pd#> <s.lba> <e.lba> - CTRL_TRIM */
+                    if (!xatoi(&ptr, &p1) ||
+                            !xatoi(&ptr, (long*)&blk[0]) ||
+                            !xatoi(&ptr, (long*)&blk[1])) {
+                        break;
+                    }
+                    PRINTF("rc=%d\r\n", disk_ioctl((BYTE)p1, CTRL_TRIM, blk));
+                    break;
+            }
+    }
+}
+
+void put_dump (
+    void* buff,             /* Pointer to the array to be dumped */
+    unsigned long addr,     /* Heading address value */
+    int len,                /* Number of items to be dumped */
+    int width               /* Size of the items (DW_CHAR, DW_SHORT, DW_LONG) */
+)
+{
+    int i;
+    unsigned char *bp;
+    unsigned short *sp;
+    unsigned long *lp;
+
+    PRINTF( "%08lx ", addr );      /* address */
+    switch ( width )  {
+        case DW_CHAR:
+            bp = (unsigned char *)buff;
+            for ( i = 0; i < len; i++ ) {       /* Hexdecimal dump */
+                PRINTF( " %02x", bp[i] );
+            }
+            PUTC(' ');
+            for ( i = 0; i < len; i++ ) {       /* ASCII dump */
+                PUTC( (bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.' );
+            }
+            break;
+        case DW_SHORT:
+            sp = (unsigned short *)buff;
+            do {                            /* Hexdecimal dump */
+                PRINTF( " %04x", *sp++ );
+            } while ( --len );
+            break;
+        case DW_LONG:
+            lp = (unsigned long *)buff;
+            do {                            /* Hexdecimal dump */
+                PRINTF( " %08lx", *lp++ );
+            } while ( --len );
+            break;
+    }
+    PUTS( "\r\n" );
+}
+
+// RTC related subroutines
+void chk_and_set_time(char *ptr)
+{
+    char buf[64];
+
+    long p1;
+    struct tm t;
+    time_t seconds;
+
+    if (xatoi(&ptr, &p1)) {
+        t.tm_year       = (uint8_t)p1 + 100;
+        pc.printf("Year:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mon        = (uint8_t)p1 - 1;
+        pc.printf("Month:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mday       = (uint8_t)p1;
+        pc.printf("Day:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_hour       = (uint8_t)p1;
+        pc.printf("Hour:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_min        = (uint8_t)p1;
+        pc.printf("Min:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_sec        = (uint8_t)p1;
+        pc.printf("Sec: %d \r\n",p1);
+        seconds = mktime(&t);
+        set_time(seconds);
+    } else {
+        seconds = time(NULL);
+    }
+    strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
+    pc.printf("[Time] %s", buf);
+}
+
+//  Get key input data
+void get_line (char *buff, int len)
+{
+    char c;
+    int idx = 0;
+
+    for (;;) {
+        c = GETC();
+        //    Added by Kenji Arai / JH1PJL   May 9th, 2010
+        if (c == '\r') {
+            buff[idx++] = c;
+            break;
+        }
+        if ((c == '\b') && idx) {
+            idx--;
+            PUTC(c);
+            PUTC(' ');
+            PUTC(c);
+        }
+        if (((uint8_t)c >= ' ') && (idx < len - 1)) {
+            buff[idx++] = c;
+            PUTC(c);
+        }
+    }
+    buff[idx] = 0;
+    PUTS("\r\n");
+}
+
+/*  Outpur LF & CR */
+void crlf( void )
+{
+    PRINTF( "\r\n" );
+}
+
+/*  Check key input */
+unsigned int check_hit_key (void)
+{
+    return ( READABLE() );
+}
+
+/*----------------------------------------------*/
+/* Get a value of the string                    */
+/*----------------------------------------------*/
+/*  "123 -5   0x3ff 0b1111 0377  w "
+        ^                           1st call returns 123 and next ptr
+           ^                        2nd call returns -5 and next ptr
+                   ^                3rd call returns 1023 and next ptr
+                          ^         4th call returns 15 and next ptr
+                               ^    5th call returns 255 and next ptr
+                                  ^ 6th call fails and returns 0
+*/
+int xatoi (         /* 0:Failed, 1:Successful */
+    char **str,     /* Pointer to pointer to the string */
+    long *res       /* Pointer to the valiable to store the value */
+)
+{
+    unsigned long val;
+    unsigned char c, r, s = 0;
+
+    *res = 0;
+    while ( (c = **str) == ' ' ) {
+        (*str)++;   /* Skip leading spaces */
+    }
+    if ( c == '-' ) {       /* negative? */
+        s = 1;
+        c = *(++(*str));
+    }
+    if ( c == '0' ) {
+        c = *(++(*str));
+        switch (c) {
+            case 'x':       /* hexdecimal */
+                r = 16;
+                c = *(++(*str));
+                break;
+            case 'b':       /* binary */
+                r = 2;
+                c = *(++(*str));
+                break;
+            default:
+                if ( c <= ' ' ) return 1;   /* single zero */
+                if ( c < '0' || c > '9' ) return 0; /* invalid char */
+                r = 8;      /* octal */
+        }
+    } else {
+        if ( c < '0' || c > '9' ) return 0; /* EOL or invalid char */
+        r = 10;         /* decimal */
+    }
+    val = 0;
+    while ( c > ' ' ) {
+        if ( c >= 'a' ) {
+            c -= 0x20;
+        }
+        c -= '0';
+        if ( c >= 17 ) {
+            c -= 7;
+            if ( c <= 9 ) {
+                return 0;   /* invalid char */
+            }
+        }
+        if ( c >= r ) {
+            return 0;   /* invalid char for current radix */
+        }
+        val = val * r + c;
+        c = *(++(*str));
+    }
+    if (s) val = 0 - val;           /* apply sign if needed */
+    *res = val;
+    return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/5_SDCard/FatFs_Mon/mon.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,15 @@
+/*
+ * mbed Application program for the mbed
+ *  FatFs Check program /monitor part
+ *
+ * Copyright (c) 2015,'18 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    May        5th, 2015
+ *      Revised:    June      14th, 2015
+ *      Revised:    April      7th, 2018
+ */
+
+//  Function prototypes --------------------------------------------------------
+void mon(void);
+uint32_t get_disk_freespace(void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/5_SDCard/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,111 @@
+/*
+ * Mbed Application program
+ *  SD Card file control function with FatFs on Mbed-os5
+ *
+ * Copyright (c) 2018 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    April      4th, 2018
+ *      Revised:    April     14th, 2018    only for TYBLE16
+ */
+
+//#define EXAMPLE_5_SDCARD
+#ifdef EXAMPLE_5_SDCARD
+
+//  Include --------------------------------------------------------------------
+#include    "mbed.h"
+#include    "SDBlockDevice.h"
+#include    "FATFileSystem.h"
+#include    "mon.h"
+#include    "TYBLE16_BASE.h"
+#include    <stdlib.h>
+
+//  Definition -----------------------------------------------------------------
+#define     USER_SW_ON      0
+
+//  Constructor ----------------------------------------------------------------
+DigitalOut      led(LED1);
+DigitalIn       user_sw(BUTTON1, PullUp);
+Serial          pc(USBTX, USBRX, 115200);
+SDBlockDevice   sd(D3, D2, D0, D1, 8000000);
+FATFileSystem   fs("fs");
+
+//  RAM ------------------------------------------------------------------------
+
+//  ROM / Constant data --------------------------------------------------------
+char *const opngmsg =
+    "\x1b[2J\x1b[H"__FILE__ "\r\n"__DATE__ " " __TIME__ " (UTC)\r\n""\r\n";
+char *const opening_msg0 = "microSD Card test program";
+char *const opening_msg1 = " -> run on Mbed OS-5\r\n";
+
+//  Function prototypes --------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+int main()
+{
+    time_t      seconds;
+    uint32_t data0 = 10000U;
+    uint32_t data1 = 20000U;
+    uint32_t data2 = 30000U;
+    uint32_t data3 = 40000U;
+    uint32_t data4 = 50000U;
+    uint32_t data5 = 60000U;
+
+    pc.puts(opngmsg);
+    // Check TYBLE-16 configuration
+    cpu_sys();
+    compile_condition();
+    if (user_sw == USER_SW_ON) {
+        mon();
+    }
+    //pc.printf("line:%d\r\n", __LINE__);
+    /* Init SD CARD reader */
+    sd.init();
+    fs.mount(&sd);
+    FILE* fp = fopen("/fs/mydata.txt", "a");
+    if (fp != 0) {
+        pc.printf("%s%s",  opening_msg0, opening_msg1);
+        fprintf(fp,"%s%s", opening_msg0, opening_msg1);
+    } else {
+        pc.printf("ERROR\r\n");
+    }
+    fclose(fp);
+    while (pc.readable()) {
+        char c = pc.getc(); // dummy read
+    }
+    while (true) {
+        uint32_t size = get_disk_freespace();
+        pc.printf("free %u  ", size);
+        fp = fopen("/fs/mydata.txt", "a");
+        if(fp != 0) {
+            char tmp[64];
+            seconds = time(NULL);
+            strftime(tmp, 64, "TYBLE16 %H:%M:%S,%Y/%m/%d,", localtime(&seconds));
+            pc.printf(tmp);
+            fprintf(fp, "%s", tmp);
+            pc.printf("%08d;%08d;%08d;%08d;%08d;%08d\r\n",
+                      ++data0, ++data1, ++data2, ++data3, ++data4, ++data5);
+            fprintf(fp, "%08d;%08d;%08d;%08d;%08d;%08d\r\n",
+                    data0,   data1,   data2,   data3,   data4,   data5);
+        } else {
+            pc.printf("ERROR\r\n");
+        }
+        fclose(fp);
+        Thread::wait(100);
+        if (user_sw == USER_SW_ON) {
+            break;
+        }
+        if (pc.readable()) {
+            mon();
+        }
+        led = !led;
+    }
+    while(true) {
+        mon();
+        NVIC_SystemReset();
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/5_SDCard/sd-driver.lib	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/armmbed/sd-driver/#6238fc964f8e8dc5c303ab75a1e6c115c7db30d7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/6_Thermo/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,206 @@
+/* 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.
+ */
+/*
+    Modified by Kenji Arai, April 14th, 2018
+        https://os.mbed.com/users/kenjiArai/
+ */
+
+//#define EXAMPLE_6_THERMO
+#ifdef EXAMPLE_6_THERMO
+
+#include    <events/mbed_events.h>
+#include    "mbed.h"
+#include    "ble/BLE.h"
+#include    "ble/services/HealthThermometerService.h"
+#include    "TYBLE16_BASE.h"
+#include    "TextLCD.h"
+#include    "BME280.h"
+
+#define NO_SENSOR   1
+#define HAS_SENSOR  0
+#define USE_LCD     0
+
+DigitalOut      led1(LED1, 1);
+Serial          pc(USBTX, USBRX);
+I2C             i2c(I2C_SDA, I2C_SCL);
+BME280          hmtp(i2c);
+#if USE_LCD
+TextLCD_I2C_N   lcd(&i2c, 0x7c, TextLCD::LCD16x2);  // LCD(Akizuki  AQM1602A)
+#endif
+
+const static char     DEVICE_NAME[]        = "TYBLE16";
+static const uint16_t uuid16_list[]
+= {GattService::UUID_HEALTH_THERMOMETER_SERVICE};
+
+char *const opngmsg =
+    "\x1b[2J\x1b[H"__FILE__ "\r\n"__DATE__ " " __TIME__ " (UTC)\r\n""\r\n";
+
+static float                      currentTemperature   = 39.6f;
+static HealthThermometerService *thermometerServicePtr;
+
+static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
+
+/* Restart Advertising on disconnection*/
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
+{
+    BLE::Instance().gap().startAdvertising();
+}
+
+void updateSensorValue(void)
+{
+    static uint32_t count = 0;
+
+#if NO_SENSOR
+    /* Do blocking calls or whatever is necessary for sensor polling.
+       In our case, we simply update the Temperature measurement. */
+    currentTemperature
+    = (currentTemperature + 0.1f > 43.0f) ? 39.6f : currentTemperature + 0.1f;
+    thermometerServicePtr->updateTemperature(currentTemperature);
+#elif HAS_SENSOR
+    currentTemperature = hmtp.getTemperature();
+    pc.printf("Temperature= %+5.2f [degC]", currentTemperature);
+    pc.printf(", count = %8u\r\n", count++);
+#if USE_LCD
+    lcd.locate(0, 1);
+    lcd.printf(" %+5.2f  %7u", currentTemperature, count);
+#endif
+    thermometerServicePtr->updateTemperature(currentTemperature);
+#else
+    thermometerServicePtr->updateTemperature(currentTemperature);
+#endif
+}
+
+void periodicCallback(void)
+{
+    led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
+
+    if (BLE::Instance().gap().getState().connected) {
+        eventQueue.call(updateSensorValue);
+    }
+}
+
+void onBleInitError(BLE &ble, ble_error_t error)
+{
+    /* Initialization error handling should go here */
+}
+
+void printMacAddress()
+{
+    /* Print out device MAC address to the console*/
+    Gap::AddressType_t addr_type;
+    Gap::Address_t address;
+    BLE::Instance().gap().getAddress(&addr_type, address);
+    pc.printf("DEVICE MAC ADDRESS: ");
+    for (int i = 5; i >= 1; i--) {
+        pc.printf("%02x:", address[i]);
+    }
+    pc.printf("%02x\r\n", address[0]);
+}
+
+void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
+{
+    BLE&        ble   = params->ble;
+    ble_error_t error = params->error;
+
+    if (error != BLE_ERROR_NONE) {
+        onBleInitError(ble, error);
+        return;
+    }
+
+    if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
+        return;
+    }
+
+    ble.gap().onDisconnection(disconnectionCallback);
+
+    /* Setup primary service. */
+    thermometerServicePtr =
+        new HealthThermometerService(ble,
+                                     currentTemperature,
+                                     HealthThermometerService::LOCATION_EAR);
+
+    /* setup advertising */
+    ble.gap().accumulateAdvertisingPayload(
+        GapAdvertisingData::BREDR_NOT_SUPPORTED |
+        GapAdvertisingData::LE_GENERAL_DISCOVERABLE
+    );
+    ble.gap().accumulateAdvertisingPayload(
+        GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
+        (uint8_t *)uuid16_list,
+        sizeof(uuid16_list)
+    );
+    ble.gap().accumulateAdvertisingPayload(
+        GapAdvertisingData::THERMOMETER_EAR
+    );
+    ble.gap().accumulateAdvertisingPayload(
+        GapAdvertisingData::COMPLETE_LOCAL_NAME,
+        (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)
+    );
+    ble.gap().setAdvertisingType(
+        GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED
+    );
+    ble.gap().setAdvertisingInterval(1000); /* 1000ms */
+    ble.gap().startAdvertising();
+
+    printMacAddress();
+}
+
+void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context)
+{
+    BLE &ble = BLE::Instance();
+    eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
+}
+
+int main()
+{
+    pc.puts(opngmsg);
+#if USE_LCD
+    lcd.locate(0, 0);
+    //        1234567890123456
+    lcd.puts("TYBLE16/Mbed-os5");
+    lcd.locate(0, 1);
+    //        1234567890123456
+    lcd.puts(" by JH1PJL      ");
+    lcd.setCursor(TextLCD_Base::CurOff_BlkOff);
+    lcd.setContrast(0x19);
+    wait(2.0f);
+#endif
+    // Check TYBLE-16 configuration
+    cpu_sys();
+    if (compile_condition() == false) {
+        pc.printf("This is wrong configuration!!\r\n");
+        while(true) {
+            led1 = !led1;
+            wait(0.2);
+        }
+    }
+#if USE_LCD
+    lcd.locate(0, 0);
+    //          123456 7890123456
+    lcd.printf("Temp: %cC   count", 0xdf);
+#endif
+    eventQueue.call_every(1000, periodicCallback);
+
+    BLE &ble = BLE::Instance();
+    ble.onEventsToProcess(scheduleBleEventsProcessing);
+    ble.init(bleInitComplete);
+
+    eventQueue.dispatch_forever();
+
+    return 0;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/7_Uart_Client/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,482 @@
+/*
+ *  ------- BLE Central/Client UART function -----------------------------------
+ *          communicate with BLE_UART_Server program
+ *      --- Tested on Switch Science mbed TY51822r3 ---
+ *
+ *  Modified by Kenji Arai
+ *      http://www.page.sannet.ne.jp/kenjia/index.html
+ *      https://os.mbed.com/users/kenjiArai/
+ *
+ *      Started:  April     8th, 2016
+ *      Revised:  June     13th, 2016
+ *      Revised:  Feburary 10th, 2018   Not set mac addr but use device name
+ *      Revised:  Feburary 11th, 2018   use mbed-os5.7.4 with CircularBuffer
+ *      Revised:  April    14th, 2018   only for TYBLE16
+ *
+ *  Original program (see original.cpp file):
+ *      S130 potential unstability case [closed] by Fabien Comte
+ *      https://devzone.nordicsemi.com/question/49705/
+ *                              s130-potential-unstability-case/
+ *      GitHub Q&A by Fabien COMTE
+ *      https://github.com/ARMmbed/ble/issues/69
+ *  Reference program:
+ *      BLE_Central_test by noboru koshinaka
+ *      https://os.mbed.com/users/noboruk/code/BLE_Central_test/
+ *  Tested Server Device:
+ *      BLE_Uart_Server
+ *      https://os.mbed.com/users/kenjiArai/code/BLE_Uart_Server/
+ */
+
+//#define EXAMPLE_7_UART_CLIENT
+#ifdef EXAMPLE_7_UART_CLIENT
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "BLE.h"
+#include "DiscoveredCharacteristic.h"
+#include "DiscoveredService.h"
+#include "UARTService.h"
+#include "CircularBuffer.h"
+
+//  Definition -----------------------------------------------------------------
+//#define     USE_MAC           // if you use mac address, please define it
+
+#define     NUM_ONCE            20
+#define     BFSIZE              (NUM_ONCE+4)
+
+//#define    USE_DEBUG_MODE
+#ifdef USE_DEBUG_MODE
+#define DBG(...) { pc.printf(__VA_ARGS__); }
+#else
+#define DBG(...)
+#endif
+
+#define SOFT_DEVICE_FATHER_HANDLE   3
+
+//  Object ---------------------------------------------------------------------
+BLE&        ble_uart = BLE::Instance();
+DigitalOut  alivenessLED(LED1, 1);
+DigitalOut  connectedLED(D0, 0);
+Serial      pc(USBTX, USBRX, 115200);
+//Serial      pc(P0_3, P0_1, 115200);     // for another board
+Ticker      ticker;
+CircularBuffer<char, 1536> ser_bf;
+Thread      tsk;
+
+//  ROM / Constant data --------------------------------------------------------
+#ifdef USE_MAC
+#warning "You need to modify below value based on your board."
+const Gap::Address_t    mac_board_0   = {0x50, 0x2b, 0xea, 0x14, 0x95, 0xd2};
+const Gap::Address_t    mac_board_1   = {0x59, 0x2c, 0xa8, 0x0e, 0xe2, 0xef};
+const Gap::Address_t    mac_board_2   = {0x0f, 0x72, 0xbf, 0x43, 0xbc, 0xd0};
+const Gap::Address_t    mac_board_3   = {0x83, 0xc9, 0x1a, 0x90, 0xdf, 0xd6};
+const Gap::Address_t    mac_board_4   = {0x43, 0xa4, 0x36, 0x11, 0x5b, 0xeb};
+#else
+const char PEER_NAME[] = "UART_PJL";
+#endif
+
+//  RAM ------------------------------------------------------------------------
+Gap::Handle_t   connectionHandle        = 0xFFFF;
+DiscoveredCharacteristic uartTXCharacteristic;
+DiscoveredCharacteristic uartRXCharacteristic;
+bool            foundUartRXCharacteristic = false;
+bool            connected2server        = false;
+bool            connection_tx           = false;
+bool            connection_rx           = false;
+UARTService *   uartServicePtr          = NULL;
+Gap::Address_t  my_mac;
+int             my_board_index          = -1;
+bool            received_uart_dat       = false;
+int8_t          uart_buffer[BFSIZE];
+uint8_t         uart_bf_len;
+volatile bool   rx_isr_busy             = false;
+
+//  Function prototypes --------------------------------------------------------
+//      BLE
+void advertisementCallback(const Gap::AdvertisementCallbackParams_t *);
+void serviceDiscoveryCallback(const DiscoveredService *);
+void characteristicDiscoveryCallback(const DiscoveredCharacteristic *);
+void discoveryTerminationCallback(Gap::Handle_t );
+void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *);
+void connectionCallback(const Gap::ConnectionCallbackParams_t *);
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *);
+//      Interrupt related
+void periodicCallback(void);
+void serialRxCallback(void);
+//      serial receiving
+void pc_ser_rx(void);
+void preparation_sending_data(void);
+//      Pre-check
+bool mac_equals(const Gap::Address_t, const Gap::Address_t);
+int  get_board_index(const Gap::Address_t);
+void adjust_line(uint8_t *);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+int main(void)
+{
+    alivenessLED = 0;
+    pc.attach(&serialRxCallback, Serial::RxIrq);
+    ticker.attach(periodicCallback, 1);
+    tsk.start(pc_ser_rx);
+    // clear terminal output
+    for (int k = 0; k < 3; k++) {
+        pc.printf("\r\n");
+    }
+    // opening message
+    pc.printf("UART Communication / Client(Central) side\r\n");
+    pc.printf("  need Server module (run BLE_Uart_Server program)\r\n");
+    // Mixed role **************************************************************
+    ble_uart.init();
+    ble_uart.gap().onConnection(connectionCallback);
+    ble_uart.gap().onDisconnection(disconnectionCallback);
+    // Client(Central) role ****************************************************
+    ble_uart.gattClient().onHVX(onReceivedDataFromDeviceCallback);
+    ble_uart.gap().setScanParams(500, 450);
+    ble_uart.gap().startScan(advertisementCallback);
+    while(true) {
+        // allow notifications from Server(Peripheral)
+        if (foundUartRXCharacteristic &&
+                !ble_uart.gattClient().isServiceDiscoveryActive()) {
+            // need to do the following only once
+            foundUartRXCharacteristic = false;
+            uint16_t value = BLE_HVX_NOTIFICATION;
+            ble_uart.gattClient().write(
+                GattClient::GATT_OP_WRITE_REQ,
+                connectionHandle,
+                uartRXCharacteristic.getValueHandle() + 1,
+                sizeof(uint16_t),
+                reinterpret_cast<const uint8_t *>(&value)
+            );
+        }
+        if (received_uart_dat == true) {
+            received_uart_dat = false;
+            for(int i = 0; i < uart_bf_len; i++) {
+                //pc.printf("%c", uart_buffer[i]);
+                pc.putc(uart_buffer[i]);
+            }
+        }
+        ble_uart.waitForEvent();
+    }
+}
+
+void periodicCallback(void)
+{
+    // Do blinky on alivenessLED to indicate system aliveness
+    alivenessLED = !alivenessLED;
+    if (connected2server) {
+        connectedLED = 1;
+    } else {
+        connectedLED = 0;
+    }
+    if (rx_isr_busy == true) {
+        rx_isr_busy = false;
+    } else {
+        tsk.signal_set(0x01);
+    }
+}
+
+void serialRxCallback()
+{
+    ser_bf.push(pc.getc());
+    rx_isr_busy = true;
+    tsk.signal_set(0x01);
+}
+
+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.empty()) {
+            if (linebf_irq_len != 0) {
+                linebf_irq[linebf_irq_len] = 0;
+                adjust_line(linebf_irq);
+                linebf_irq_len = 0;
+                uartTXCharacteristic.write(NUM_ONCE, linebf_irq);
+            }
+        }
+        while(!ser_bf.empty()) {
+            char c;
+            ser_bf.pop(c);
+            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;
+                    uartTXCharacteristic.write(linebf_irq_len, linebf_irq);
+                    linebf_irq_len = 0;
+                    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 <NUM_ONCE; bf++, i++) {
+        c = *bf;
+        if (c == 0) {
+            break;
+        }
+    }
+    for (; i < NUM_ONCE; bf++, i++) {
+        *bf = 0x11;
+    }
+    *(bf + 1) = 0;
+}
+
+void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *params)
+{
+    DBG(
+        "received HVX callback for handle %u; type %s\r\r\n",
+        params->handle,
+        (params->type == BLE_HVX_NOTIFICATION) ? "notification" : "indication"
+    );
+    if (params->type == BLE_HVX_NOTIFICATION) {
+        if ((params->handle
+                == uartRXCharacteristic.getValueHandle()) && (params->len > 0)) {
+            uart_bf_len = params->len;
+            strcpy((char *)uart_buffer, (char *)params->data);
+            received_uart_dat = true;
+        }
+    }
+}
+
+#ifdef USE_MAC
+
+bool mac_equals(const Gap::Address_t mac_1, const Gap::Address_t mac_2)
+{
+    DBG("Address: ");
+    for (int i = 0; i < 6; i++) {
+        DBG("0x%02x ", mac_1[i]);
+    }
+    DBG("\r\n");
+    for (int i = 0; i < 6; i++) {
+        if (mac_1[i] != mac_2[i]) {
+            DBG("0x%02x != 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
+            return false;
+        } else {
+            DBG("0x%02x == 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
+        }
+    }
+    return true;
+}
+
+int get_board_index(const Gap::Address_t mac)
+{
+    if (mac_equals(mac, mac_board_0)) {
+        return 0;
+    }
+    if (mac_equals(mac, mac_board_1)) {
+        return 1;
+    }
+    if (mac_equals(mac, mac_board_2)) {
+        return 2;
+    }
+    if (mac_equals(mac, mac_board_3)) {
+        return 3;
+    }
+    if (mac_equals(mac, mac_board_4)) {
+        return 4;
+    }
+    return -1;
+}
+
+// Client(Central) role ********************************************************
+void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
+{
+    // connections
+    int peer_board_index = get_board_index(params->peerAddr);
+    if (peer_board_index != -1) {
+        pc.printf("");
+        pc.printf(
+            "adv peerAddr [%02x %02x %02x %02x %02x %02x]\r\n",
+            params->peerAddr[5], params->peerAddr[4], params->peerAddr[3],
+            params->peerAddr[2], params->peerAddr[1], params->peerAddr[0]
+        );
+        pc.printf(
+            "rssi=%+4d, isScanResponse %u, AdvertisementType %u\r\n",
+            params->rssi, params->isScanResponse, params->type
+        );
+        ble_uart.gap().connect(
+            params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+    }
+}
+
+#else
+
+// Client(Central) role ********************************************************
+void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
+{
+    bool name_match = false;
+
+    // parse the advertising payload, looking for data type COMPLETE_LOCAL_NAME
+    // The advertising payload is a collection of key/value records where
+    // byte 0: length of the record excluding this byte
+    // byte 1: The key, it is the type of the data
+    // byte [2..N] The value. N is equal to byte0 - 1
+
+    for( uint8_t i = 0; i < params->advertisingDataLen; ++i) {
+        const uint8_t record_length = params->advertisingData[i];
+        if (record_length == 0) {
+            continue;
+        }
+        const uint8_t type = params->advertisingData[i + 1];
+        const uint8_t* value = params->advertisingData + i + 2;
+        const uint8_t value_length = record_length - 1;
+
+        if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
+            if ((value_length == sizeof(PEER_NAME))
+                    && (memcmp(value, PEER_NAME, value_length) == 0)) {
+                pc.printf(
+                    "\r\nadv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, ",
+                    params->peerAddr[5], params->peerAddr[4],
+                    params->peerAddr[3], params->peerAddr[2],
+                    params->peerAddr[1], params->peerAddr[0],
+                    params->rssi
+                );
+                pc.printf(
+                    "isScanResponse %u, AdvertisementType %u\r\n",
+                    params->isScanResponse, params->type
+                );
+                name_match = true;
+                break;
+            }
+        }
+        i += record_length;
+    }
+    if( name_match != true ) {
+        return;
+    }
+
+    pc.printf("Found device name : %s\r\n",PEER_NAME);
+    // connections
+    ble_uart.gap().connect(params->peerAddr,
+                           Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+}
+
+#endif
+
+void serviceDiscoveryCallback(const DiscoveredService *service)
+{
+    DBG("service found...\r\n");
+    if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        DBG(
+            "Service UUID-%x attrs[%u %u]\r\n",
+            service->getUUID().getShortUUID(),
+            service->getStartHandle(),
+            service->getEndHandle()
+        );
+    } else {
+        DBG("Service UUID-");
+        const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
+        for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
+            DBG("%02x", longUUIDBytes[i]);
+        }
+        DBG(" attrs[%u %u]\r\n",
+            service->getStartHandle(), service->getEndHandle());
+    }
+}
+
+void characteristicDiscoveryCallback(
+    const DiscoveredCharacteristic *characteristicP)
+{
+    DBG(
+        " C UUID-%x valueAttr[%u] props[%x]\r\n",
+        characteristicP->getUUID().getShortUUID(),
+        characteristicP->getValueHandle(),
+        (uint8_t)characteristicP->getProperties().broadcast()
+    );
+    if (characteristicP->getUUID().getShortUUID()
+            == UARTServiceTXCharacteristicShortUUID) {
+        DBG("Sevice TX 0x%04x\r\n", UARTServiceTXCharacteristicShortUUID);
+        uartTXCharacteristic = *characteristicP;
+        connection_tx = true;
+    } else if (characteristicP->getUUID().getShortUUID()
+               == UARTServiceRXCharacteristicShortUUID) {
+        DBG("Sevice RX 0x%04x\r\n", UARTServiceRXCharacteristicShortUUID);
+        uartRXCharacteristic = *characteristicP;
+        foundUartRXCharacteristic = true;
+        connection_rx = true;
+    }
+}
+
+void discoveryTerminationCallback(Gap::Handle_t connectionHandle)
+{
+    DBG("terminated SD for handle=%u\r\n", connectionHandle);
+}
+
+// Mixed role ******************************************************************
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
+{
+    if (params->role == Gap::CENTRAL) {
+        pc.printf("connected as Client(Central) (handle = %d)\r\n\r",
+                  params->handle);
+        connected2server = true;
+        connectionHandle = params->handle;
+        ble_uart.gattClient().onServiceDiscoveryTermination(
+            discoveryTerminationCallback);
+        ble_uart.gattClient().launchServiceDiscovery(
+            params->handle,
+            serviceDiscoveryCallback,
+            characteristicDiscoveryCallback
+        );
+    }
+    pc.printf(
+        "Client(Central/Myself)       %02x:%02x:%02x:%02x:%02x:%02x\r\n",
+        params->ownAddr[5], params->ownAddr[4], params->ownAddr[3],
+        params->ownAddr[2], params->ownAddr[1], params->ownAddr[0]
+    );
+    pc.printf(
+        "Connected Server(Peripheral) %02x:%02x:%02x:%02x:%02x:%02x\r\n",
+        params->peerAddr[5], params->peerAddr[4], params->peerAddr[3],
+        params->peerAddr[2], params->peerAddr[1], params->peerAddr[0]
+    );
+}
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
+{
+    DBG("handle = %d ", params->handle);
+    pc.printf(" -> disconnected\r\n", params->handle);
+    connected2server = false;
+//    connection_1st = false;
+    connection_tx = false;
+    connection_rx = false;
+    if (params->handle == SOFT_DEVICE_FATHER_HANDLE) {
+        ble_uart.startAdvertising();                    // restart advertising
+    } else {
+        ble_uart.gap().startScan(advertisementCallback);// restart scan
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/7_Uart_Client/original.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,614 @@
+#if 0
+//-------------------------------------------------------------------------------------------------
+//  ORIGINAL PROGRAM
+//      S130 potential unstability case [closed] by Fabien Comte
+//      https://devzone.nordicsemi.com/question/49705/s130-potential-unstability-case/
+//
+#include "mbed.h"
+#include "BLE.h"
+#include "UARTService.h"
+#include "ble/DiscoveredCharacteristic.h"
+#include "ble/DiscoveredService.h"
+#include "ble/service/UARTService.h"
+
+#define SOFT_DEVICE_FATHER_HANDLE 3
+
+#define BOARDS_COUNT 3
+
+const Gap::Address_t mac_board_0 = {0xb8, 0xac, 0x4e, 0x8d, 0x8b, 0xeb}; 
+const Gap::Address_t mac_board_1 = {0x9c, 0x43, 0x62, 0x30, 0xaf, 0xd2}; 
+const Gap::Address_t mac_board_2 = {0x5f, 0x1a, 0x9e, 0x6a, 0x63, 0xdd}; 
+
+
+// tiny ble board
+#define LED_GREEN   p21
+#define LED_RED     p22
+#define LED_BLUE    p23
+#define BUTTON_PIN  p17
+#define BATTERY_PIN p1
+
+#define MPU6050_SDA p12
+#define MPU6050_SCL p13
+
+#define UART_TX     p9
+#define UART_RX     p11
+#define UART_CTS    p8
+#define UART_RTS    p10
+
+DigitalOut led(LED_RED);
+DigitalOut alivenessLED(LED_GREEN);
+InterruptIn button(BUTTON_PIN);
+AnalogIn battery(BATTERY_PIN);
+Serial pc(UART_TX, UART_RX);
+
+bool mac_equals(const Gap::Address_t mac_1, const Gap::Address_t mac_2)
+{
+    #if 0
+        if (mac_1[0] != mac_2[0])
+        {
+            return false;
+        }
+        if (mac_1[1] != mac_2[1])
+        {
+            return false;
+        }
+        if (mac_1[2] != mac_2[2])
+        {
+            return false;
+        }
+        if (mac_1[3] != mac_2[3])
+        {
+            return false;
+        }
+        if (mac_1[4] != mac_2[4])
+        {
+            return false;
+        }
+        if (mac_1[5] != mac_2[5])
+        {
+            return false;
+        }
+    #else
+        for (int i = 0; i < 6; i++)
+        {
+            if (mac_1[i] != mac_2[i])
+            {
+                //pc.printf("0x%02x != 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
+                return false;
+            }
+            else
+            {
+                //pc.printf("0x%02x == 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
+            }
+        }
+    #endif
+    return true;
+}
+
+int get_board_index(const Gap::Address_t mac)
+{
+    if (mac_equals(mac, mac_board_0))
+    {
+        return 0;
+    }
+    if (mac_equals(mac, mac_board_1))
+    {
+        return 1;
+    }
+    if (mac_equals(mac, mac_board_2))
+    {
+        return 2;
+    }
+    
+    return -1;
+}
+
+void periodicCallback(void) 
+{
+    alivenessLED = !alivenessLED; /* do blinky on alivenessLED while we're waiting for BLE events */
+}
+
+
+// Mixed role ****************************************************
+BLE ble;
+Gap::Address_t my_mac;
+int my_board_index = -1;
+
+// Device role ****************************************************
+UARTService * uartServicePtr = NULL;
+const static char     DEVICE_NAME[]        = "ChangeMe!!"; // change this
+static const uint16_t uuid16_list[] = {UARTServiceShortUUID};
+volatile int central_handle = -1;
+
+
+// Central role ****************************************************
+Gap::Handle_t connectionHandle = 0xFFFF;
+DiscoveredCharacteristic uartTXCharacteristic;
+DiscoveredCharacteristic uartRXCharacteristic;
+bool foundUartRXCharacteristic = false;
+volatile int device_handle = -1;
+
+
+// Device role ****************************************************
+void onReceivedDataFromCentralCallback(const GattWriteCallbackParams *params) 
+{
+    if (uartServicePtr != NULL)
+    {
+        if ((params->handle == uartServicePtr->getTXCharacteristicHandle()) && (params->len >= 1)) 
+        {
+            if (params->data[0] != '0')
+            {
+                led = 1;
+            }
+            else
+            {
+                led = 0;
+            }
+            
+            for(int i = 0; i < params->len; i++) 
+            {
+                pc.printf("%c", params->data[i]);
+            }
+            
+            pc.printf(" (%d, %d)\r\n", params->handle, params->connHandle);
+        }
+    }
+}
+
+// Central role ****************************************************
+void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) 
+{
+    // do connections like a triangle
+    int peer_board_index = get_board_index(params->peerAddr);
+    
+    int next_board_index = my_board_index + 1;
+    if (next_board_index >= BOARDS_COUNT)
+    {
+        next_board_index = 0;
+    }
+    
+    //pc.printf("adv %d, %d, %d\r\n", peer_board_index, my_board_index, next_board_index);
+    
+    // force order
+    if ((central_handle != -1) || (peer_board_index == 0))
+    {
+        if (peer_board_index == next_board_index)
+        {
+            //pc.printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
+            //       params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
+            //       params->rssi, params->isScanResponse, params->type);
+        
+            ble.gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+        }
+    }
+}
+
+void serviceDiscoveryCallback(const DiscoveredService *service) 
+{
+    if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) 
+    {
+        pc.printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
+    } 
+    else
+    {
+        //pc.printf("S UUID-");
+        const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
+        for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) 
+        {
+            pc.printf("%02x", longUUIDBytes[i]);
+        }
+        pc.printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
+    }
+}
+
+void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) 
+{
+    //pc.printf("  C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
+    if (characteristicP->getUUID().getShortUUID() == UARTServiceTXCharacteristicShortUUID) 
+    { 
+        pc.printf("fit TX 0x%04x\r\n", UARTServiceTXCharacteristicShortUUID);
+        /* !ALERT! Alter this filter to suit your device. */
+        uartTXCharacteristic        = *characteristicP;
+    }
+    else if (characteristicP->getUUID().getShortUUID() == UARTServiceRXCharacteristicShortUUID) 
+    { 
+        pc.printf("fit RX 0x%04x\r\n", UARTServiceRXCharacteristicShortUUID);
+        /* !ALERT! Alter this filter to suit your device. */
+        uartRXCharacteristic        = *characteristicP;
+        foundUartRXCharacteristic = true;
+    }
+}
+
+void discoveryTerminationCallback(Gap::Handle_t connectionHandle) 
+{
+    pc.printf("terminated SD for handle %u\r\n", connectionHandle);
+}
+
+void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *params) 
+{
+    //pc.printf("received HVX callback for handle %u; type %s\r\r\n", params->handle, (params->type == BLE_HVX_NOTIFICATION) ? "notification" : "indication");
+    if (params->type == BLE_HVX_NOTIFICATION)
+    {
+        if ((params->handle == uartRXCharacteristic.getValueHandle()) && (params->len > 0))
+        {
+            for (int i = 0; i < params->len; i++) 
+            {
+                pc.printf("%c", params->data[i]);
+            }
+            
+            pc.printf(" (%d, %d)\r\n", params->handle, params->connHandle);
+        }
+    }
+    else
+    {
+        pc.printf("%d\r\n", params->type);
+    }
+}
+
+// Mixed role ****************************************************
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params) 
+{
+    if (params->role == Gap::CENTRAL) 
+    {
+        if (central_handle == -1)
+        {
+            ble.stopAdvertising(); // stop advertising during discovery, incoming connection breaks discovery
+        }
+        
+        device_handle = params->handle;
+        pc.printf("connected as central (handle = %d)\r\n\r", params->handle);
+        connectionHandle = params->handle;
+        ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
+        int ret = ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, UARTServiceShortUUID/*, 0xa001*/);
+        
+        if (ret != BLE_ERROR_NONE)
+        {
+            pc.printf("launchServiceDiscovery failed error = %d\r\n\r", ret);
+        }
+    }
+    else
+    {
+        central_handle = params->handle;
+        pc.printf("connected as device (handle = %d)\r\n\r", params->handle);
+        
+        //pc.printf("Conn. params => min=%d, max=%d, slave=%d, supervision=%d\r\n", params->connectionParams->minConnectionInterval, params->connectionParams->maxConnectionInterval, params->connectionParams->slaveLatency, params->connectionParams->connectionSupervisionTimeout);
+        /*
+        Gap::ConnectionParams_t connectionParams;
+        connectionParams.minConnectionInterval        = 6;
+        connectionParams.maxConnectionInterval        = 12;
+        connectionParams.slaveLatency                 = 40;
+        connectionParams.connectionSupervisionTimeout = 500;
+        
+        int ret = ble.updateConnectionParams(params->handle, &connectionParams);
+        if (ret != BLE_ERROR_NONE) 
+        {
+            pc.printf("failed to update connection parameter\r\n");
+        }
+        */
+    }
+    pc.printf("own %02x:%02x:%02x:%02x:%02x:%02x (%s), peer %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n", params->ownAddr[5], params->ownAddr[4], params->ownAddr[3], params->ownAddr[2], params->ownAddr[1], params->ownAddr[0], (params->ownAddrType == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random", params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0], (params->peerAddrType == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random");
+}
+
+void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) 
+{
+    char * ascii_reason = "?";
+    switch (reason)
+    {
+        case Gap::CONNECTION_TIMEOUT:
+            ascii_reason = "connection timeout";
+            break;    
+        case Gap::REMOTE_USER_TERMINATED_CONNECTION:
+            ascii_reason = "user terminated connection";
+            break;    
+        case Gap::REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES:
+            ascii_reason = "low resources";
+            break;    
+        case Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF:
+            ascii_reason = "power off";
+            break;    
+        case Gap::LOCAL_HOST_TERMINATED_CONNECTION:
+            ascii_reason = "host terminated connection";
+            break;    
+        case Gap::CONN_INTERVAL_UNACCEPTABLE:
+            ascii_reason = "interval unacceptable";
+            break;    
+        default:
+            ascii_reason = "unknown";
+            break;
+    }
+    
+    pc.printf("disconnected (reason = %s, handle = %d)\r\n", ascii_reason, handle);
+    
+    
+    if (handle == SOFT_DEVICE_FATHER_HANDLE)
+    {
+        central_handle = -1;
+        // restart advertising
+        ble.startAdvertising(); 
+    }
+    else
+    {
+        device_handle = -1;
+        // restart scan
+        ble.gap().startScan(advertisementCallback);
+    }
+}
+
+
+
+void serialTxCallback() 
+{
+
+}
+ 
+int rx_char = -1;
+void serialRxCallback() 
+{   
+    if (rx_char != -1)
+    {
+        pc.printf("overflow\r\n");
+    }
+     
+     //computer.putc(computer.getc());
+     rx_char = pc.getc();
+}
+
+/*
+void gattServerOnDataSent(unsigned count)
+{
+ 
+}
+*/
+
+
+int main(void) 
+{
+    alivenessLED = 0;
+    
+    pc.baud(115200);
+    //pc.attach(&serialTxCallback, Serial::TxIrq);
+    pc.attach(&serialRxCallback, Serial::RxIrq);
+    
+    // clear terminal output
+    for (int k = 0; k < 32; k++)
+    {
+        pc.printf("\r\n");    
+    }
+    
+    pc.printf("Central and device\r\n");
+   
+    Ticker ticker;
+    ticker.attach(periodicCallback, 1);
+    
+    
+    // Mixed role ****************************************************
+    ble.init();
+    
+    Gap::AddressType_t my_mac_type;
+    ble.gap().getAddress(&my_mac_type, my_mac);
+    my_board_index = get_board_index(my_mac);
+    pc.printf("me %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");
+    
+
+    // try to speed up but looks like if it was ignored
+    Gap::ConnectionParams_t fast;
+    if (ble.getPreferredConnectionParams(&fast) != BLE_ERROR_NONE) 
+    {
+        pc.printf("getPreferredConnectionParams failed\r\n");
+    }
+    else
+    {
+        fast.minConnectionInterval = 16; // 20 ms
+        fast.maxConnectionInterval = 32; // 40 ms
+        fast.slaveLatency = 0;
+        if (ble.gap().setPreferredConnectionParams(&fast) != BLE_ERROR_NONE) 
+        {
+            pc.printf("setPreferredConnectionParams failed\r\n");
+        }
+    }
+    ble.gap().onConnection(connectionCallback);
+    ble.gap().onDisconnection(disconnectionCallback);
+    
+    // Device role ****************************************************
+    ble.gattServer().onDataWritten(onReceivedDataFromCentralCallback);
+    //ble.gattServer().onDataSent(gattServerOnDataSent);
+
+    UARTService uartService(ble);
+    uartServicePtr = &uartService;
+
+    // setup advertising
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // BLE only, no classic BT
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // UUID's broadcast in advertising packet
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // advertising type
+    ble.setAdvertisingInterval(100); 
+    
+    // Central role ****************************************************
+    ble.gattClient().onHVX(onReceivedDataFromDeviceCallback);
+    ble.gap().setScanParams(500, 450);
+    
+    
+    // start advertising and scan
+    ble.startAdvertising(); 
+    ble.gap().startScan(advertisementCallback);
+
+    while (true) 
+    {
+          // allow notifications from device
+          if (foundUartRXCharacteristic && !ble.gattClient().isServiceDiscoveryActive()) 
+          {
+            foundUartRXCharacteristic = false; /* need to do the following only once */
+ 
+            uint16_t value = BLE_HVX_NOTIFICATION;
+            int ret = ble.gattClient().write(GattClient::GATT_OP_WRITE_REQ,
+                                   connectionHandle,
+                                   uartRXCharacteristic.getValueHandle() + 1, /* HACK Alert. We're assuming that CCCD descriptor immediately follows the value attribute. */
+                                   sizeof(uint16_t),                          /* HACK Alert! size should be made into a BLE_API constant. */
+                                   reinterpret_cast<const uint8_t *>(&value));
+                                   
+            if (ret == BLE_ERROR_NONE) 
+            {
+                pc.printf("\r\ndevice notifications enabled\r\n");
+            }
+            else
+            {
+                switch (ret)
+                {
+                    case BLE_STACK_BUSY:
+                        foundUartRXCharacteristic = true; // retry later
+                        break;
+                    case BLE_ERROR_NO_MEM:
+                        foundUartRXCharacteristic = true; // retry later
+                        break;
+                    case BLE_ERROR_INVALID_STATE:
+                        pc.printf("\r\ndevice notifications enable failed\r\n");
+                        break;
+                    default:
+                        break;
+                }
+            }
+            
+            if (!foundUartRXCharacteristic)
+            {
+                if (central_handle == -1)
+                {
+                    ble.startAdvertising();        
+                }
+            }
+        }
+        
+        // while a new char from computer is available
+        while (rx_char != -1)
+        { 
+            uint8_t temp[20];
+            int length = 1;
+            
+            uint8_t command = rx_char;
+            rx_char = -1;
+        
+            // if special char to test a 20 bytes frame
+            /*
+            if (command == '*')
+            {
+                pc.printf("20 chars\r\n");
+                
+                int c = 0;
+                for (c = 0; c < 20; c++)
+                {
+                    temp[c] = 'a' + c;
+                }
+                length = 20;
+            }
+            else
+            {
+                temp[0] = command;
+            }
+            */
+            temp[0] = command;
+       
+            // to central
+            //if (command == '1')     
+            {
+                if (central_handle != -1)
+                {
+                    // device to central
+                    while (1)
+                    {             
+                        if (central_handle == -1)
+                        {
+                            pc.printf("\r\ndisconnected 1 (to central)\r\n");
+                            break;
+                        }              
+                        if (!ble.gap().getState().connected) 
+                        {
+                            pc.printf("\r\ndisconnected 2 (to central)\r\n");
+                            break;
+                        }
+                        int ret = ble.gattServer().write(uartServicePtr->getRXCharacteristicHandle(), temp, length);
+                        
+                        if (ret == BLE_ERROR_NONE) 
+                        {
+                            //pc.printf("\r\nok (to central)\r\n");
+                            break;
+                        }
+                        else if (ret == BLE_STACK_BUSY)
+                        {
+                            //pc.printf("\r\nbusy (to central)\r\n");
+                            //break;
+                        }
+                        else if (ret == BLE_ERROR_OPERATION_NOT_PERMITTED)
+                        {
+                            pc.printf("\r\nnot permitted (to central)\r\n");
+                            break;
+                        }
+                        else if (ret == BLE_ERROR_INVALID_STATE)
+                        {
+                            pc.printf("\r\ninvalid state (to central)\r\n");
+                            break;
+                        }
+                        else
+                        {
+                            pc.printf("\r\ncode %d (to central)\r\n", ret);
+                            break;
+                        }
+                    }
+                }
+                else
+                {
+                    pc.printf("\r\nnot connected with central\r\n");
+                }
+            }
+             
+            // to device
+            //if (command == '2')   
+            {
+                if (device_handle != -1)
+                {
+                    // central to device 
+                    while (1)
+                    {               
+                        if (device_handle == -1)
+                        {
+                            pc.printf("\r\ndisconnected (to device)\r\n");
+                            break;
+                        }     
+                        int ret = uartTXCharacteristic.write(length, temp);
+                        if (ret == BLE_ERROR_NONE) 
+                        {
+                            //pc.printf("\r\nok (to device)\r\n");
+                            break;
+                        }
+                        else if (ret == BLE_STACK_BUSY) 
+                        {
+                            //pc.printf("\r\nbusy (to device)\r\n");
+                            //break;
+                        }
+                        else if (ret == BLE_ERROR_OPERATION_NOT_PERMITTED)
+                        {
+                            pc.printf("\r\nnot permitted (to device)\r\n");
+                            break;
+                        }
+                        else if (ret == BLE_ERROR_INVALID_STATE)
+                        {
+                            pc.printf("\r\ninvalid state (to device)\r\n");
+                            break;
+                        }
+                        else
+                        {
+                            pc.printf("\r\ncode %d (to device)\r\n", ret);
+                            break;
+                        }
+                    }
+                }
+                else
+                {
+                    pc.printf("\r\nnot connected with device\r\n");
+                }
+            }
+        }
+        
+        ble.waitForEvent(); // save power
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/8_Uart_Server/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,585 @@
+/* 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.
+ */
+
+/*
+ *  ------- 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
+ *      https://os.mbed.com/users/kenjiArai/
+ *
+ *      Started:  March     7th, 2016
+ *      Revised:  June     13th, 2016
+ *      Revised:  Feburary 10th, 2018   Not set mac addr but use device name
+ *      Revised:  Feburary 11th, 2018   use mbed-os5.7.4 with CircularBuffer
+ *      Revised:  April    14th, 2018   modification only for TYBLE16
+ *
+ *  Original program:
+ *      BLE_LoopbackUART
+ *      https://developer.mbed.org/teams/Bluetooth-Low-Energy/
+ *                                  code/BLE_LoopbackUART/
+ *  Reference program:
+ *      BLE_Peripheral_test by noboru koshinaka
+ *      https://os.mbed.com/users/noboruk/code/BLE_Peripheral_test/
+ *  Tested Client Device:
+ *      BLE_Uart_Client
+ *      https://os.mbed.com/users/kenjiArai/code/BLE_Uart_Client/
+ */
+
+//#define EXAMPLE_8_UART_SERVER
+#ifdef EXAMPLE_8_UART_SERVER
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "BLE.h"
+#include "UARTService.h"
+#include "nRF51_Vdd.h"
+#include "nRF51_WakeUp.h"
+#include "CircularBuffer.h"
+
+//  Definition -----------------------------------------------------------------
+//#define     USE_MAC           // if you use mac address, please define it
+
+#define     NUM_ONCE            20
+#define     BFSIZE              (NUM_ONCE+4)
+
+// Please refer nRF51_WakeUP library
+#define     GOTO_SLEEP_MODE     0
+#if GOTO_SLEEP_MODE
+#warning "Make sure!! -> You need to connected P0_21(LED1) and P0_0"
+#endif
+
+//#define    USE_DEBUG_MODE
+#ifdef USE_DEBUG_MODE
+#define DEBUG(...) { printf(__VA_ARGS__); }
+#else
+#define DEBUG(...)
+#endif
+
+//  Object ---------------------------------------------------------------------
+BLE&            ble_uart = BLE::Instance();
+DigitalOut      connectedLED(LED1);
+//InterruptIn     wake_up_sw(P0_1);
+//nRF51_WakeUp    wakeup(P0_21, P0_0);
+nRF51_Vdd       vdd(3.0f, 2.2f);
+Serial          pc(USBTX, USBRX, 115200);
+//Serial        pc(P0_3, P0_1, 115200);     // for another board
+UARTService     *uartServicePtr;
+Ticker          ticker;
+CircularBuffer<char, 1536> ser_bf;
+Thread          tsk;
+Mutex           bletx_mutex;
+
+//  ROM / Constant data --------------------------------------------------------
+#warning "You need to confirm your device name."
+const static char DEVICE_NAME[] = "UART_PJL";
+
+//  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 --------------------------------------------------------
+//      BLE
+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 command(uint8_t *cmd);
+void action_tx_help(void);
+void action_tx_vdd(void);
+void action_tx_temperature(void);
+//void action_tx_wait_time(uint8_t *);
+void action_tx_quit(void);
+static int  xatoi (char **, int32_t *);
+void adjust_line(uint8_t *);
+//      Interrupt related
+//void interrupt_by_sw(void);
+void serialRxCallback(void);
+void periodicCallback(void);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+int main(void)
+{
+    connectedLED = 0;
+    pc.attach(&serialRxCallback, Serial::RxIrq);
+    ticker.attach(periodicCallback, 1);
+    tsk.start(pc_ser_rx);
+    // clear terminal output
+    for (int k = 0; k < 3; 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_uart.init();
+    Gap::AddressType_t my_mac_type;
+    ble_uart.gap().getAddress(&my_mac_type, my_mac);
+    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(
+        "  My device name : %s\r\n", DEVICE_NAME);
+    pc.printf(
+        "  My mac data %02x:%02x:%02x:%02x:%02x:%02x\r\n",
+        my_mac[5], my_mac[4], my_mac[3], my_mac[2], my_mac[1], my_mac[0]
+    );
+#ifdef USE_MAC
+    pc.printf(
+        "  mac_board_x   = {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 data(mac_board_x line (x=0,1,2,...))\r\n");
+    pc.printf(
+        "  into Client/main.cpp [ROM / Constant data] area\r\n");
+#endif
+    ble_uart.onDisconnection(disconnectionCallback);
+    ble_uart.onDataWritten(onDataWritten_action);
+    /* setup advertising */
+    ble_uart.accumulateAdvertisingPayload(
+        GapAdvertisingData::BREDR_NOT_SUPPORTED);
+    ble_uart.setAdvertisingType(
+        GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble_uart.accumulateAdvertisingPayload(
+        GapAdvertisingData::COMPLETE_LOCAL_NAME,
+        (const uint8_t *)DEVICE_NAME,
+        sizeof(DEVICE_NAME)
+    );
+    ble_uart.accumulateAdvertisingPayload(
+        GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
+        (const uint8_t *)UARTServiceUUID_reversed,
+        sizeof(UARTServiceUUID_reversed)
+    );
+    // Advertize Interval
+    ble_uart.setAdvertisingInterval(1000); /* 1000ms;in multiples of 0.625ms.*/
+    // Start
+    ble_uart.startAdvertising();
+    UARTService uartService(ble_uart);
+    uartServicePtr = &uartService;
+    while(true) {
+        if (time_out) {
+#if GOTO_SLEEP_MODE
+            wakeup.set_and_wait(sleep_time);
+            while(true) {   // never come here but just in case
+                deepsleep();
+            }
+#endif
+        }
+        if (trigger_transmit) {
+            static uint8_t cmd_buf[BFSIZE];
+            static volatile bool   flag_continue = 0;
+            trigger_transmit = false;
+            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;
+                }
+            }
+        }
+        ble_uart.waitForEvent();
+    }
+}
+
+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;
+#if 0
+            case 'w':
+                action_tx_wait_time(cmd);
+                break;
+#endif
+            case 'h':
+            case '?':
+                action_tx_help();
+                break;
+            default:
+                //pc.printf("\r\nStep(%u)\r\n", __LINE__);
+                break;
+        }
+    }
+}
+
+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.push(pc.getc());
+    rx_isr_busy = true;
+    tsk.signal_set(0x01);
+}
+
+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.empty()) {
+            if (linebf_irq_len != 0) {
+                linebf_irq[linebf_irq_len] = 0;
+                adjust_line(linebf_irq);
+                linebf_irq_len = 0;
+                bletx_mutex.lock();
+                ble_uart.updateCharacteristicValue(
+                    uartServicePtr->getRXCharacteristicHandle(),
+                    linebf_irq,
+                    NUM_ONCE
+                );
+                bletx_mutex.unlock();
+            }
+        }
+        while(!ser_bf.empty()) {
+            char c;
+            ser_bf.pop(c);
+            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_uart.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 <NUM_ONCE; bf++, i++) {
+        c = *bf;
+        if (c == 0) {
+            break;
+        }
+    }
+    for (; i < NUM_ONCE; bf++, i++) {
+        *bf = 0x11;
+    }
+    *(bf + 1) = 0;
+}
+
+void onDataWritten_action(const GattWriteCallbackParams *params)
+{
+    if ((uartServicePtr != NULL) &&
+            (params->handle == uartServicePtr->getTXCharacteristicHandle())) {
+        strcpy((char *)rx_buf, (const char *)params->data);
+        trigger_transmit = true;
+    }
+}
+
+void action_tx_help()
+{
+    //          12345678901234567890
+    sprintf((char *)tx_buf,"  ~?:help\r\n");
+    tx_len = strlen((const char *)tx_buf);
+    Update_Values();
+    Thread::wait(200);
+    //          12345678901234567890
+    sprintf((char *)tx_buf,"  ~v:vdd\r\n");
+    tx_len = strlen((const char *)tx_buf);
+    Update_Values();
+    Thread::wait(200);
+    //          12345678901234567890
+    sprintf((char *)tx_buf,"  ~t:temperature\r\n");
+    tx_len = strlen((const char *)tx_buf);
+    Update_Values();
+    Thread::wait(200);
+#if 0
+    //          12345678901234567890
+    sprintf((char *)tx_buf,"  ~w:wait, w 120\r\n");
+    tx_len = strlen((const char *)tx_buf);
+    Update_Values();
+    Thread::wait(200);
+#endif
+    //          12345678901234567890
+    sprintf((char *)tx_buf,"  ~q:quit/sleep\r\n");
+    tx_len = strlen((const char *)tx_buf);
+    Update_Values();
+    Thread::wait(200);
+}
+
+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();
+}
+
+#if 0
+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();
+}
+#endif
+
+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();
+    Thread::wait(1000);
+    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
+static int xatoi (char **str, int32_t *res)
+{
+    unsigned long val;
+    unsigned char c, radix, s = 0;
+
+    for (;;) {
+        c = **str;
+        if (c == 0) {
+            return 0;
+        }
+        if (c == '-') {
+            break;
+        }
+        if (c == '+') {
+            (*str)++;
+            c = **str;
+        }
+        if (c>='0'&& c<='9') {
+            break;
+        } else {
+            (*str)++;
+            c = **str;
+        }
+    }
+    if (c == '-') {
+        s = 1;
+        c = *(++(*str));
+    }
+    if (c == '0') {
+        c = *(++(*str));
+        if (c <= ' ') {
+            *res = 0;
+            return 1;
+        }
+        if (c == 'x') {
+            radix = 16;
+            c = *(++(*str));
+        } else {
+            if (c == 'b') {
+                radix = 2;
+                c = *(++(*str));
+            } else {
+                if ((c >= '0')&&(c <= '9')) {
+                    radix = 8;
+                }   else {
+                    return 0;
+                }
+            }
+        }
+    } else {
+        if ((c < '1')||(c > '9')) {
+            return 0;
+        }
+        radix = 10;
+    }
+    val = 0;
+    while (c > ' ') {
+        if (c >= 'a') c -= 0x20;
+        c -= '0';
+        if (c >= 17) {
+            c -= 7;
+            if (c <= 9) return 0;
+        }
+        if (c >= radix) return 0;
+        val = val * radix + c;
+        c = *(++(*str));
+    }
+    if (s) val = -val;
+    *res = val;
+    return 1;
+}
+
+#if 0
+void interrupt_by_sw() // Go to sleep
+{
+    NVIC_SystemReset();
+    // Not come here (Just in case)
+    sleep();
+}
+#endif
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
+{
+    DEBUG("Disconnected!\r\n");
+    DEBUG("Restarting the advertising process\r\n");
+    ble_uart.startAdvertising();
+}
+
+void Update_Values(void)
+{
+    bletx_mutex.lock();
+    ble_uart.updateCharacteristicValue(
+        uartServicePtr->getRXCharacteristicHandle(),
+        tx_buf,
+        tx_len
+    );
+    bletx_mutex.unlock();
+    tx_len = 0;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/9_Monitor/debug_tools/debug_common.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,162 @@
+/*
+ * mbed Application program (part of debuf_xxx.cpp)
+ *
+ *  Copyright (c) 2010-2014,'18 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    October   16th, 2014
+ *      Revised:    Nobember  30th, 2016
+ *      Revised:    April     14th, 2018
+ */
+
+//  Include --------------------------------------------------------------------
+#include "mon_hw_common.h"
+
+//  Definition -----------------------------------------------------------------
+#define BAUD(x)                 pc.baud(x)
+#define GETC(x)                 pc.getc(x)
+#define PUTC(x)                 pc.putc(x)
+#define PRINTF(...)             pc.printf(__VA_ARGS__)
+#define READABLE(x)             pc.readable(x)
+
+#define BAUD_RATE 9600
+
+//  Object ---------------------------------------------------------------------
+extern Serial pc;
+
+//  RAM ------------------------------------------------------------------------
+char linebuf[64];
+int buf_size = sizeof(linebuf);
+
+//  ROM / Constant data --------------------------------------------------------
+char *const mon_msg =
+    "Debug Interface for mbed system, created on UTC: "__DATE__"("__TIME__")";
+
+//  Function prototypes --------------------------------------------------------
+extern int mon_hw(void);
+extern void get_freq(int pr);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+//  Put \r\n
+void put_rn ( void )
+{
+    PUTC('\r');
+    PUTC('\n');
+}
+
+//  Put \r
+void put_r ( void )
+{
+    PUTC('\r');
+}
+
+// Put ", "
+void put_lin ( void )
+{
+    PRINTF(", ");
+}
+
+// Put space n
+void put_spc( uint8_t n)
+{
+    for(; n > 0; n--) {
+        PUTC(' ');
+    }
+}
+
+//  Change string -> integer
+int xatoi (char **str, int32_t *res)
+{
+    unsigned long val;
+    unsigned char c, radix, s = 0;
+
+    while ((c = **str) == ' ') (*str)++;
+    if (c == '-') {
+        s = 1;
+        c = *(++(*str));
+    }
+    if (c == '0') {
+        c = *(++(*str));
+        if (c <= ' ') {
+            *res = 0;
+            return 1;
+        }
+        if (c == 'x') {
+            radix = 16;
+            c = *(++(*str));
+        } else {
+            if (c == 'b') {
+                radix = 2;
+                c = *(++(*str));
+            } else {
+                if ((c >= '0')&&(c <= '9')) {
+                    radix = 8;
+                }   else {
+                    return 0;
+                }
+            }
+        }
+    } else {
+        if ((c < '1')||(c > '9')) {
+            return 0;
+        }
+        radix = 10;
+    }
+    val = 0;
+    while (c > ' ') {
+        if (c >= 'a') c -= 0x20;
+        c -= '0';
+        if (c >= 17) {
+            c -= 7;
+            if (c <= 9) return 0;
+        }
+        if (c >= radix) return 0;
+        val = val * radix + c;
+        c = *(++(*str));
+    }
+    if (s) val = -val;
+    *res = val;
+    return 1;
+}
+
+void get_line_no_param (char *buff)
+{
+    get_line(buff, buf_size);
+}
+
+// RTC related subroutines
+static void chk_and_set_time(char *ptr)
+{
+//unsigned long p1;
+    int32_t p1;
+    static struct tm t;
+    time_t seconds;
+    char buf[40];
+
+    if (xatoi(&ptr, &p1)) {
+        t.tm_year       = (uint8_t)p1 + 100;
+        PRINTF("Year:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mon        = (uint8_t)p1 - 1;
+        PRINTF("Month:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mday       = (uint8_t)p1;
+        PRINTF("Day:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_hour       = (uint8_t)p1;
+        PRINTF("Hour:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_min        = (uint8_t)p1;
+        PRINTF("Min:%d ",p1);
+        xatoi( &ptr, &p1 );
+        t.tm_sec        = (uint8_t)p1;
+        PRINTF("Sec: %d \r\n",p1);
+        seconds = mktime(&t);
+        set_time(seconds);
+    }
+    seconds = time(NULL);
+    strftime(buf, 40, "%B %d,'%y, %H:%M:%S", localtime(&seconds));
+    PRINTF("Date: %s\r\n", buf);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/9_Monitor/debug_tools/debug_nRF5x.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,198 @@
+/*
+ * mbed Application program
+ *
+ *  Copyright (c) 2016,'18 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    Feburary   1st, 2016
+ *      Revised:    Nobember   1st, 2016
+ *      Revised:    April     14th, 2018
+ *
+ */
+
+#if defined(TARGET_NRF51822)
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "debug_common.h"
+#include "nrf_soc.h"            // for internal Thermo sensoer
+#include "nRF51_Vdd.h"          // Read nRF5x Vdd voltage
+#include "nrf_delay.h"
+
+//  Object ---------------------------------------------------------------------
+nRF51_Vdd   vdd_mon(3.6f, 2.6f);
+DigitalOut  p_out(LED1);
+
+//  Definition -----------------------------------------------------------------
+
+//  RAM ------------------------------------------------------------------------
+
+//  ROM / Constant data --------------------------------------------------------
+
+//  Function prototypes --------------------------------------------------------
+extern void cpu_sys(void);
+void debug_core(void);
+void ble_stack_stop(void);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+//  Help Massage
+void msg_hlp (void)
+{
+    PRINTF(mon_msg);
+    put_rn();
+    PRINTF("c - CPU VDD & Temp info");
+    put_rn();
+    PRINTF("l - Low current (Sleep Mode)");
+    put_rn();
+#if 0
+    PRINTF("t - Test Radio module");
+    put_rn();
+#endif
+    PRINTF("s - CPU system info");
+    put_rn();
+    PRINTF("r - Reset(by Software)");
+    put_rn();
+    PRINTF("x - Goto HW monitor");
+    put_rn();
+    PRINTF("q - Return to main");
+    put_rn();
+    PRINTF(" --- special function (1,2...) see debugging_nRF51.h");
+    put_rn();
+    PRINTF("1 - Try new function");
+    put_rn();
+}
+
+// ---------- Program starts here! ---------------------------------------------
+void debug_interface(uint8_t mode)
+{
+    BAUD(BAUD_RATE);
+    if (mode) {
+        debug_core();
+    } else {
+        if(READABLE()) {
+            unsigned char c = GETC();   // dummy read
+            debug_core();
+        }
+    }
+}
+
+void step_by_step(char c)
+{
+    PRINTF("Waiting key input");
+    while (!READABLE()) {
+        ;
+    }
+    PRINTF("--- step %c", c);
+    put_rn();
+    c = GETC();   // dummy read
+}
+
+void debug_core(void)
+{
+    char *ptr;
+    int32_t p_temp;
+    float temperature;
+
+    uint32_t n;
+
+    put_rn();
+    put_rn();
+    PRINTF("%s [Help:'?' key]", mon_msg);
+    put_rn();
+    for (;;) {
+        put_r();
+        PUTC('>');
+        ptr = linebuf;
+        get_line(ptr, sizeof(linebuf));
+        put_r();
+        switch (*ptr++) {
+                //--------------------------------------------------------------
+                //  CPU VDD Voltage and Chip temperature
+                //--------------------------------------------------------------
+            case 'c' :
+                NRF_TEMP->TASKS_START = 1;
+                while (NRF_TEMP->EVENTS_DATARDY == 0) {
+                    ;
+                }
+                NRF_TEMP->EVENTS_DATARDY = 0;
+                if ((NRF_TEMP->TEMP & 0x00000200) != 0) {
+                    p_temp = (NRF_TEMP->TEMP | 0xFFFFFC00);
+                } else {
+                    p_temp = NRF_TEMP->TEMP;
+                }
+                NRF_TEMP->TASKS_STOP = 1; // Stop the temperature measurement
+                temperature = (float)p_temp / 4.0f;
+                PRINTF("nRF5x\r\nChip temperature: %+4.1fdegC", temperature);
+                put_rn();
+                // Vdd voltage
+                PRINTF("Vdd: %4.3fV", vdd_mon.read_real_value());
+                put_rn();
+                break;
+                //--------------------------------------------------------------
+                //  Something new and try new functions
+                //--------------------------------------------------------------
+
+                // Please see following file
+#include "debugging_nRF5x.h"
+
+                //--------------------------------------------------------------
+                //  Go to Low current (Sleep mode)
+                //--------------------------------------------------------------
+            case 'l' :
+                PRINTF("Enter Sleep mode (Please push RESET button)");
+                put_rn();
+                while(true) {
+                    sleep();
+                    //__WFI();
+                    //__WFE();
+                }
+                //       SCB->AIRCR = 0x05fa0004;    // System RESET!!
+                //break;
+                //--------------------------------------------------------------
+                //  CPU system info
+                //--------------------------------------------------------------
+            case 's' :
+                cpu_sys();
+                break;
+                //--------------------------------------------------------------
+                //  System reset
+                //--------------------------------------------------------------
+            case 'r' :
+                SCB->AIRCR = 0x05fa0004;    // System RESET!!
+                // Not come here (Just in case)
+                deepsleep();
+                break;
+                //--------------------------------------------------------------
+                //  help
+                //--------------------------------------------------------------
+            case '?' :
+                msg_hlp();
+                break;
+                //--------------------------------------------------------------
+                //  Go to special command
+                //--------------------------------------------------------------
+            case 'x' :
+                mon_hw();
+                PRINTF("->Came back monitor\r\n");
+                break;
+                //--------------------------------------------------------------
+                //  Go back to main()
+                //--------------------------------------------------------------
+            case 'q' :        // Quit
+                PRINTF("\rReturn to main\r\n");
+                //PRINTF("cannot control anymore from here\r\n");
+                return;
+                //--------------------------------------------------------------
+                //    no support
+                //--------------------------------------------------------------
+            default:
+                PUTC('?');
+                put_rn();
+                break;
+        }
+    }
+}
+
+#endif  // defined(TARGET_NRF51822)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/9_Monitor/debug_tools/debugging_nRF5x.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,218 @@
+/*
+ * mbed Application program
+ *
+ *  Copyright (c) 2016,'18Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    Feburary   1st, 2016
+ *      Revised:    Feburary  18th, 2016
+ *      Revised:    April     14th, 2018
+ *
+ */
+
+//------------------------------------------------------------------------------
+//  Something new and try new functions
+//------------------------------------------------------------------------------
+#define NRF_RTC2_BASE       0x40024000UL
+#define NRF_RTC2            ((NRF_RTC_Type *) NRF_RTC2_BASE)
+#define MAX_RTC_TASKS_DELAY 47  //Maximum delay until an RTC task is executed
+
+// You do NOT need switch() sentence!!
+
+case '1' :
+step_by_step('1');
+sd_power_system_off();
+step_by_step('2');
+NRF_RTC2->PRESCALER = 0; /* for no pre-scaling. */
+NRF_RTC2->TASKS_START = 1;
+n = NRF_RTC2->COUNTER;
+wait(0.1);
+if ( n == NRF_RTC2->COUNTER)
+{
+    PRINTF("RTC2 is not running\r\n");
+} else
+{
+    PRINTF("RTC2 is running & counter = %d\r\n", n);
+}
+step_by_step('3');
+n = NRF_RTC2->COUNTER;
+wait(0.1);
+if ( n == NRF_RTC2->COUNTER)
+{
+    PRINTF("RTC2 is not running\r\n");
+} else
+{
+    PRINTF("RTC2 is running & counter = %d\r\n", n);
+}
+step_by_step('4');
+n = NRF_RTC0->COUNTER;
+wait(0.1);
+if ( n == NRF_RTC0->COUNTER)
+{
+    PRINTF("RTC0 is not running\r\n");
+} else
+{
+    PRINTF("RTC0 is running & counter = %d\r\n", n);
+}
+n = NRF_RTC1->COUNTER;
+wait(0.1);
+if ( n == NRF_RTC1->COUNTER)
+{
+    PRINTF("RTC1 is not running\r\n");
+    NRF_RTC1->PRESCALER = 0; /* for no pre-scaling. */
+    NRF_RTC1->TASKS_START = 1;
+    wait(0.5);
+    n = NRF_RTC1->COUNTER;
+    wait(0.1);
+    if ( n == NRF_RTC1->COUNTER) {
+        PRINTF("RTC1 is not running\r\n");
+    } else {
+        PRINTF("RTC1 is running & counter = %d\r\n", n);
+    }
+} else
+{
+    PRINTF("RTC1 is running & counter = %d\r\n", n);
+}
+break;
+case '2' :
+step_by_step('1');
+// Stop Radio
+NRF_RADIO->SHORTS          = 0;
+NRF_RADIO->EVENTS_DISABLED = 0;
+NRF_RADIO->TEST            = 0;
+NRF_RADIO->TASKS_DISABLE   = 1;
+while (NRF_RADIO->EVENTS_DISABLED == 0)
+{
+    ;// Do nothing.
+}
+NRF_RADIO->EVENTS_DISABLED = 0;
+// Set RTC1 for wake-up
+NVIC_ClearPendingIRQ(RTC1_IRQn);
+NVIC_DisableIRQ(RTC1_IRQn);
+NRF_RTC1->TASKS_STOP = 1;
+nrf_delay_us(MAX_RTC_TASKS_DELAY);
+NRF_RTC1->TASKS_CLEAR = 1;
+nrf_delay_us(MAX_RTC_TASKS_DELAY);
+NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
+NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
+NRF_RTC1->INTENCLR = RTC_INTENSET_OVRFLW_Msk;
+NRF_RTC1->EVTENCLR = RTC_EVTEN_OVRFLW_Msk;
+NRF_RTC1->EVENTS_COMPARE[0] = 0;
+NRF_RTC1->EVTENCLR = 0x000f0003; // all clear
+NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE0_Msk;
+NRF_RTC1->PRESCALER = 4095;
+// Set wake-up time
+NRF_RTC1->CC[0] = 50;
+// GPIOE
+NRF_GPIO->PIN_CNF[21] =
+    (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+    | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+    | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
+    | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
+    | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
+NRF_GPIOTE->CONFIG[0] =
+    (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
+    | (21 << GPIOTE_CONFIG_PSEL_Pos)
+    | (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos);
+// Set PPI
+NRF_PPI->CH[0].EEP = (uint32_t)&NRF_RTC1->EVENTS_COMPARE[0];
+NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
+// Enable only PPI channels 0
+NRF_PPI->CHEN = PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos;
+// Restart RTC1
+NRF_RTC1->TASKS_START = 1;
+nrf_delay_us(MAX_RTC_TASKS_DELAY);
+// DEBUG
+PRINTF("NRF_RTC1->PRESCALER=0x%x\r\n", NRF_RTC1->PRESCALER);
+PRINTF("NRF_RTC1->EVTEN=0x%x\r\n", NRF_RTC1->EVTEN);
+PRINTF("NRF_RTC1->COUNTER=0x%x\r\n", NRF_RTC1->COUNTER);
+PRINTF("NRF_RTC1->EVENTS_COMPARE[0]=0x%x\r\n", NRF_RTC1->EVENTS_COMPARE[0]);
+PRINTF("NRF_RTC1->CC[0]=0x%x\r\n", NRF_RTC1->CC[0]);
+do
+{
+    PRINTF("NRF_RTC1->EVENTS_COMPARE[0]=");
+    PRINTF("%d", NRF_RTC1->EVENTS_COMPARE[0]);
+    PRINTF(" %d", NRF_RTC1->CC[0]);
+    PRINTF(" %d\r\n", NRF_RTC1->COUNTER);
+    nrf_delay_us(125000);
+} while(NRF_RTC1->EVENTS_COMPARE[0] == 0);
+PRINTF("NRF_RTC1->EVENTS_COMPARE[0]=");
+PRINTF("%d", NRF_RTC1->EVENTS_COMPARE[0]);
+PRINTF(" %d", NRF_RTC1->CC[0]);
+PRINTF(" %d\r\n", NRF_RTC1->COUNTER);
+step_by_step('4');
+// GPIOE
+NRF_GPIO->PIN_CNF[21] =
+    (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+    | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+    | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
+    | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
+    | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
+NRF_GPIOTE->CONFIG[0] =
+    (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
+    | (21 << GPIOTE_CONFIG_PSEL_Pos)
+    | (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos);
+// RTC1
+NRF_RTC1->TASKS_STOP = 1;
+NRF_RTC1->EVENTS_COMPARE[0] = 0;
+NRF_RTC1->EVTENCLR = 0x000f0003; // all clear
+NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE0_Msk;
+NRF_RTC1->TASKS_CLEAR = 1;
+NRF_RTC1->CC[0] = 100;
+NRF_RTC1->PRESCALER = 4095;
+do
+{
+    NRF_RTC1->TASKS_STOP = 1;
+    NRF_RTC1->PRESCALER = 4095;
+    PRINTF("Retry PRESCALER setting\r\n");
+} while (NRF_RTC1->PRESCALER != 4095);
+PRINTF("NRF_RTC1->PRESCALER=0x%x\r\n", NRF_RTC1->PRESCALER);
+PRINTF("NRF_RTC1->EVTEN=0x%x\r\n", NRF_RTC1->EVTEN);
+PRINTF("NRF_RTC1->COUNTER=0x%x\r\n", NRF_RTC1->COUNTER);
+PRINTF("NRF_RTC1->EVENTS_COMPARE[0]=0x%x\r\n", NRF_RTC1->EVENTS_COMPARE[0]);
+PRINTF("NRF_RTC1->CC[0]=0x%x\r\n", NRF_RTC1->CC[0]);
+// PPI
+NRF_PPI->CH[0].EEP = (uint32_t)&NRF_RTC1->EVENTS_COMPARE[0];
+NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
+// Enable only PPI channels 0
+NRF_PPI->CHEN = PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos;
+NRF_RTC1->TASKS_START = 1;
+do
+{
+    PRINTF("NRF_RTC1->EVENTS_COMPARE[0]=");
+    PRINTF("%d", NRF_RTC1->EVENTS_COMPARE[0]);
+    PRINTF(" %d", NRF_RTC1->CC[0]);
+    PRINTF(" %d\r\n", NRF_RTC1->COUNTER);
+} while(NRF_RTC1->EVENTS_COMPARE[0] == 0);
+PRINTF("NRF_RTC1->EVENTS_COMPARE[0]=");
+PRINTF("%d", NRF_RTC1->EVENTS_COMPARE[0]);
+PRINTF(" %d", NRF_RTC1->CC[0]);
+PRINTF(" %d\r\n", NRF_RTC1->COUNTER);
+break;
+case '3' :
+step_by_step('x');
+p_out = 1;
+step_by_step('y');
+p_out = 0;
+step_by_step('z');
+for (int8_t n =0; n < 20; n++)
+{
+    p_out = 1;
+    wait_ms(100);
+    p_out = 0;
+    wait_ms(100);
+}
+break;
+case '4' :
+PRINTF("Please make your own command!!\r\n");
+PRINTF("Please see 9_Monitor\debug_tool\debugging_nRF5x.h\r\n");
+PRINTF("line:%d\r\n", __LINE__);
+step_by_step('x');
+;
+step_by_step('y');
+;
+step_by_step('z');
+;
+break;
+
+// You don't need any terminate bracket such as '}'
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/9_Monitor/debug_tools/mon_hw_common.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,59 @@
+/*
+ * mbed Headder file for Hardware Monitor
+ *
+ *  Copyright (c) 2014,'18 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    June       1st, 2014
+ *      Revised:    Nobember   2nd, 2014
+ *      Revised:    April     14th, 2018
+ *
+ */
+
+//  Object --------------------------------------------------------------------
+extern Serial pc;
+
+//  Definition -----------------------------------------------------------------
+#define BAUD_RATE 9600
+
+#define BAUD(x)             pc.baud(x)
+#define GETC(x)             pc.getc(x)
+#define PUTC(x)             pc.putc(x)
+#define PRINTF(...)         pc.printf(__VA_ARGS__)
+#define READABLE(x)         pc.readable(x)
+
+// Range check status
+#define ERR_NOTHING         0
+#define ERR_MODIFY_SIZ      1
+#define ERR_OUT_OF_RANGE    2
+
+// Reg. Size
+#define SIZE8               8
+#define SIZE16              16
+#define SIZE32              32
+#define SIZE_FULL           32
+#define SIZE_X              32
+
+//  RAM ------------------------------------------------------------------------
+extern char linebuf[];
+extern int buf_size;
+
+#if USE_MEM
+typedef struct {
+    int32_t mstr;
+    int32_t msiz;
+    int32_t mtmp;
+    int32_t mold;
+    uint8_t  mflg;
+    uint8_t  mbhw;
+} MEMO;
+static MEMO mem;
+#endif
+
+//  Function prototypes --------------------------------------------------------
+extern void put_rn ( void );
+extern void put_r ( void );
+extern void put_lin ( void );
+extern void put_spc( uint8_t n);
+extern void get_line (char *buff, int len);
+extern int xatoi (char **str, int32_t *res);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/9_Monitor/debug_tools/mon_hw_config.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,33 @@
+/*
+ * mbed Headder file for Hardware Monitor
+ *
+ *  Copyright (c) 2014,'16,'18 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    June       1st, 2014
+ *      Revised:    Feburary  13th, 2016
+ *      Revised:    April     14th, 2018
+ *
+ */
+
+// CPU nRF51822 / mbed nRF51822, mbed Nano, mbed which is used nRF51822 chip
+//     mon_hw_config.h     mon_hw_mem.h    mon_hw_nRF51.cpp
+
+#ifndef     _MON_HW_CONF_H_
+#define     _MON_HW_CONF_H_
+
+//  Definition -----------------------------------------------------------------
+//      Please select each function for your purpose (selected = set 1)
+
+#define     USE_MEM             1
+#define     USE_PORT            1
+#define     USE_FREQ            1
+#define     USE_UART            1
+#define     USE_SPI             1
+#define     USE_I2C             1
+#define     USE_ADC             1
+#define     USE_TIMER           1
+#define     USE_SYS             1
+#define     USE_POWER           1
+
+#endif  // _MON_HW_CONF_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/9_Monitor/debug_tools/mon_hw_mem.h	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,242 @@
+/*
+ * Monitor program / Memory control part
+ *
+ *	Copyright (c) 2010-2014,'16,'18 Kenji Arai / JH1PJL
+ *	http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Separated:	October   13th, 2014	from mon_hw.cpp
+ *      Revised:	Feburary   4th, 2016
+ *      Revised:    April     14th, 2018
+ *
+ */
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+static void mem_cnfg_init( uint8_t print )
+{
+    uint32_t a, b, c;
+
+    a = NRF_FICR->CODEPAGESIZE;
+    b = NRF_FICR->CODESIZE;
+    c = a * b;
+    mem_range[0][1] = mem_range[0][0] + c -1;
+    if (print) {
+        PRINTF("CODEPAGESIZE:%d, CODESIZE:%d\r\nFLASH:0x%08x-0x%08x\r\n",
+               a, b, mem_range[0][0], mem_range[0][1]);
+    }
+    a = NRF_FICR->NUMRAMBLOCK;
+    b = NRF_FICR->SIZERAMBLOCKS;
+    c = a * b;
+    mem_range[1][1] = mem_range[1][0] + c -1;
+    if (print) {
+        PRINTF("NUMRAMBLOCK:%d, SIZERAMBLOCKS:%d\r\nRAM:  0x%08x-0x%08x\r\n",
+               a, b, mem_range[1][0], mem_range[1][1]);
+    }
+}
+
+//  Range check for Memory dump
+static void check_range( MEMO * mem )
+{
+    uint8_t  i;
+    uint32_t m;
+
+    mem->mflg = ERR_NOTHING;
+    for ( i = 0 ; i < 6 ; i++ ) {
+        if ( mem->mstr >= mem_range[i][0]) {
+            if ( mem->mstr < mem_range[i][1] ) {
+                m = mem->mstr + mem->msiz;
+                if ( m < mem_range[i][1]) {
+                    return;            // no modification
+                } else {
+                    m = mem_range[i][1];
+                    mem->msiz = m - mem->mstr + 1;
+                    mem->mflg = ERR_MODIFY_SIZ;
+                    return;            // modified size
+                }
+            }
+        }
+    }
+    mem->mflg = ERR_OUT_OF_RANGE;
+    mem->mstr = 0;
+    mem->msiz = 0;
+    return ;
+}
+
+//  Memory dump error massage
+void error_print ( unsigned char flg )
+{
+    switch (flg) {
+        case ERR_MODIFY_SIZ :
+            put_r();
+            PRINTF("Reach to out of range");
+            put_rn();
+            break;
+        case ERR_OUT_OF_RANGE :
+            put_r();
+            PRINTF("Not in a memory area");
+            put_rn();
+            break;
+        case ERR_NOTHING :
+        default :
+            ;
+    }
+}
+
+//  Print memory contents
+void put_dump (const unsigned char *buff, unsigned long ofs, int cnt)
+{
+    int n;
+
+    PRINTF("%08lX ", ofs);
+    for(n = 0; n < cnt; n++) {		// show hex
+        PRINTF(" %02X", buff[n]);
+    }
+    for(; n < 16; n++) {			// fullfil remained space
+        PRINTF("   ");
+    }
+    PUTC(' ');
+    for(n = 0; n < cnt; n++) {		// show char
+        if ((buff[n] < 0x20)||(buff[n] >= 0x7F)) {
+            PUTC('.');
+        } else {
+            PUTC(buff[n]);
+        }
+    }
+    put_rn();
+}
+
+// dump memory with error check
+void dump_w_err_ckeck ( char **ptr, MEMO * mem )
+{
+    check_range (mem);
+    for (*ptr=(char*)mem->mstr; mem->msiz >= 16; *ptr += 16, mem->msiz -= 16) {
+        put_r();
+        put_dump((unsigned char*)*ptr, (unsigned int)*ptr, 16);
+    }
+    if (mem->msiz) {
+        put_dump((unsigned char*)*ptr, (unsigned int)*ptr, mem->msiz);
+    }
+    error_print(mem->mflg);
+}
+
+static void mem_inf (char *ptr)
+{
+    put_r();
+    PRINTF("Mem. Mode d <address> [<count>], s, <ret> or f, q, ?");
+    put_rn();
+    mem_cnfg_init(0);
+    mem.mstr = mem_range[0][0];     // default start address = Flash
+    mem.msiz =256;
+    mem.mold = 0;
+    mem.mtmp = 0;
+    mem.mflg = 0;
+    for (; mem.mflg != 0xff;) {
+        PRINTF("m>");
+        ptr = linebuf;
+        get_line(ptr, buf_size);
+        put_r();
+        switch(*ptr++) {
+            case 'd' :    // d <address> [<count>] - Dump memory
+                mem.mtmp = mem.mstr;
+                if (!xatoi(&ptr, &mem.mstr)) {
+                    mem.mstr = mem.mtmp;
+                }
+                if (!xatoi(&ptr, &mem.msiz)) {
+                    mem.msiz = 256;
+                }
+                mem.mtmp = mem.msiz;
+                dump_w_err_ckeck(&ptr, &mem);
+                mem.mold = mem.mstr;
+                mem.mstr += mem.mtmp;
+                break;
+            case 'f' :        // next
+            case 'n' :
+            case 0x0d :
+                mem.msiz = 256;
+                mem.mtmp = mem.msiz;
+                dump_w_err_ckeck(&ptr, &mem);
+                mem.mold = mem.mstr;
+                mem.mstr += 256;
+                break;
+            case 'q' :        // quit
+                mem.mflg = 0xff;
+                break;
+            case 'b' :        // Back to more
+                if (mem.mold == 0) {
+                    ;
+                } else {
+                    mem.mold -= 256;
+                }
+            case 'k' :        // keep previous address
+                mem.mstr = mem.mold;
+                mem.msiz = 256;
+                mem.mtmp = mem.msiz;
+                dump_w_err_ckeck(&ptr, &mem);
+                mem.mstr += 256;
+                break;
+            case 'a' :        // start RAM top
+                mem.mstr = mem_range[1][0];
+                mem.msiz =256;
+                mem.mold = 0;
+                mem.mtmp = 0;
+                mem.mflg = 0;
+                dump_w_err_ckeck(&ptr, &mem);
+                mem.mstr += 256;
+                break;
+            case 'o' :        // start ROM top
+                mem.mstr = mem_range[0][0];
+                mem.msiz =256;
+                mem.mold = 0;
+                mem.mtmp = 0;
+                mem.mflg = 0;
+                dump_w_err_ckeck(&ptr, &mem);
+                mem.mstr += 256;
+                break;
+            case 's' :
+                PRINTF("Memory Configuration");
+                put_rn();
+                PRINTF("%s0x%08lx to 0x%08lx ",
+                       rmsg0, mem_range[0][0], mem_range[0][1]);
+                put_rn();
+                PRINTF("%s0x%08lx to 0x%08lx ",
+                       rmsg1, mem_range[1][0], mem_range[1][1]);
+                put_rn();
+                PRINTF("%s0x%08lx to 0x%08lx ",
+                       rmsg2, mem_range[2][0], mem_range[2][1]);
+                put_rn();
+                PRINTF("%s0x%08lx to 0x%08lx ",
+                       rmsg3, mem_range[3][0], mem_range[3][1]);
+                put_rn();
+                PRINTF("%s0x%08lx to 0x%08lx ",
+                       rmsg4, mem_range[4][0], mem_range[4][1]);
+                put_rn();
+                PRINTF("%s0x%08lx to 0x%08lx ",
+                       rmsg5, mem_range[5][0], mem_range[5][1]);
+                put_rn();
+                break;
+            case '?' :
+                PRINTF("d <address> [<count>] - Dump memory");
+                put_rn();
+                PRINTF("s  - Show memory structure ");
+                put_rn();
+                PRINTF("o  - Dump memory / start from ROM top");
+                put_rn();
+                PRINTF("a  - Dump memory / start from RAM top");
+                put_rn();
+                PRINTF("k  - Dump memory / keep same 256bytes");
+                put_rn();
+                PRINTF("b  - Dump memory / before 256bytes");
+                put_rn();
+                PRINTF("<RET> or f, n - Dump memory / next 256bytes");
+                put_rn();
+                PRINTF("q  - Exit memory mode");
+                put_rn();
+                break;
+            default:
+                PUTC('?');
+                put_rn();
+        }
+    }
+    PRINTF("Return to All Mode");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/9_Monitor/debug_tools/mon_hw_nRF5x.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,1227 @@
+/*
+ * mbed Application program for the mbed nRF51 series
+ *
+ *  Copyright (c) 2016,'18 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    Feburary   1st, 2016
+ *      Revised:    Feburary  18th, 2016
+ *      Revised:    April     14th, 2018
+ *
+ */
+
+#if defined(TARGET_NRF51822)
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "mon_hw_config.h"
+#include "mon_hw_common.h"
+#include "TYBLE16_BASE.h"
+
+//  Object ---------------------------------------------------------------------
+
+//  Definition -----------------------------------------------------------------
+#define SIMPLE_NOT_SHOW      1   // 1=Simple
+
+//  RAM ------------------------------------------------------------------------
+uint32_t SystemFrequency;
+#if USE_MEM
+//  Memory range data (This is special case: save in RAM area! (others mbed's are in FLASH))
+//      follows are only initial data and check FICR data for ROM & RAM size
+uint32_t mem_range[][2] = { // Memory access range
+    // On-chip non-volatile memory    //128 or 256KB Flash
+    { 0x00000000, 0x0003ffff },
+    // On-chip SRAM                    //16 or 32KB RAM
+    { 0x20000000, 0x20007fff },
+    { 0x10000000, 0x1000007f },            // FICR
+    { 0x10001000, 0x100010ff },            // UICR
+    { 0x40000000, 0x400245ff },            // Peripheral
+    { 0x50000500, 0x500007ff }             // GPIO
+};
+#endif  // USE_MEM
+
+//  ROM / Constant data --------------------------------------------------------
+char *const mon_msg =
+    "HW monitor only for mbed nRF51 series created on "__DATE__","__TIME__"";
+
+char *const xmsg0 = "Not implimented yet";
+char *const hmsg0 = "m  - Entry Memory Mode";
+char *const hmsg1 = "m>? -> Help ";
+char *const hmsg2 = "r  - Show I2C,SPI,UART,Timer,ADC Reg.";
+char *const hmsg3 = "r>? -> Help";
+char *const hmsg4 = "c  - CPU information";
+char *const hmsg5 = "f  - Show Clock frequency";
+char *const hmsg6 = "p  - GPIO information";
+char *const hmsg7 = "w  - Power management";
+char *const hmsg8 = "x  - Special command for Debug";
+char *const hmsg9 = "q  - Quit (back to called routine)";
+
+//  Function prototypes --------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+// No function
+void not_yet_impliment( void )
+{
+    put_r();
+    PRINTF(xmsg0);
+    put_rn();
+}
+
+// No function
+#if (USE_MEM==0)||(USE_PORT==0)||(USE_UART==0)|| \
+    (USE_SPI==0)||(USE_I2C==0)||(USE_SYS==0)
+void not_select( void )
+{
+    PRINTF("Not select the function (refer mon_hw_config.h)");
+    put_rn();
+}
+#endif
+
+//  Help Massage
+void msg_hlp_hw (void)
+{
+    PRINTF(mon_msg);
+    put_rn();
+    PRINTF(hmsg0);
+    put_rn();
+    PRINTF(hmsg1);
+    put_rn();
+    PRINTF(hmsg2);
+    put_rn();
+    PRINTF(hmsg3);
+    put_rn();
+    PRINTF(hmsg4);
+    put_rn();
+    PRINTF(hmsg5);
+    put_rn();
+    PRINTF(hmsg6);
+    put_rn();
+    PRINTF(hmsg7);
+    put_rn();
+    PRINTF(hmsg8);
+    put_rn();
+    PRINTF(hmsg9);
+    put_rn();
+}
+
+#if USE_MEM
+char *const rmsg0 = "FLASH      ";
+char *const rmsg1 = "SRAM       ";
+char *const rmsg2 = "FIR        ";
+char *const rmsg3 = "UIR        ";
+char *const rmsg4 = "Peripheral ";
+char *const rmsg5 = "GPIO       ";
+
+#include "mon_hw_mem.h"
+#endif   // USE_MEM
+
+//  Show Xbit register contents
+void reg_print(uint16_t size, uint16_t reg)
+{
+    uint16_t i, j, k, n;
+
+    if (size == 8) {
+        PRINTF(" 7, 6, 5, 4, 3, 2, 1, 0");
+        put_rn();
+        i = 8;
+        n = 0x80;
+    } else if (size == 16) {
+        PRINTF( "15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0" );
+        put_rn();
+        i = 16;
+        n = 0x8000;
+    } else {
+        PRINTF("0x%08x", reg);
+        return;
+    }
+    PUTC(' ');
+    for (; i>0; i--) {
+        k = n >> (size-i);
+        j = reg & k;
+        if (j) {
+            PUTC('1');
+        } else {
+            PUTC('0');
+        }
+        PUTC(' ');
+        PUTC(' ');
+    }
+    PRINTF("  (0x%04x)", reg);
+}
+
+uint8_t bit_position(uint32_t x)
+{
+    uint8_t n;
+
+    for (n = 0; n < 32; n++) {
+        x = x >> 1UL;
+        if (x & 0x1) {
+            break;
+        }
+    }
+    return n;
+}
+
+#if USE_FREQ
+void freq_reg(void)
+{
+    uint32_t r0;
+
+//    NRF_CLOCK->TASKS_HFCLKSTART = 0xffffffff;
+//    NRF_CLOCK->HFCLKRUN = 0x00010001;
+
+    put_r();
+    //  Start HFCLK clock source
+    r0 = NRF_CLOCK->TASKS_HFCLKSTART;
+    PRINTF( "TASKS_HFCLKSTART:" );
+    reg_print(SIZE32, r0);
+    put_rn();
+    //  Stop HFCLK clock source
+    r0 = NRF_CLOCK->TASKS_HFCLKSTOP;
+    PRINTF( "TASKS_HFCLKSTOP: " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Start LFCLK clock source
+    r0 = NRF_CLOCK->TASKS_LFCLKSTART;
+    PRINTF( "TASKS_LFCLKSTART:" );
+    reg_print(SIZE32, r0);
+    put_rn();
+    //  Stop LFCLK clock source
+    r0 = NRF_CLOCK->TASKS_LFCLKSTOP;
+    PRINTF( "TASKS_LFCLKSTOP: " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Start calibration of LFCLK RC oscillator
+    r0 = NRF_CLOCK->TASKS_CAL;
+    PRINTF( "TASKS_CAL:       " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    //  Start calibration timer
+    r0 = NRF_CLOCK->TASKS_CTSTART;
+    PRINTF( "TASKS_CTSTART:   " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Stop calibration timer
+    r0 = NRF_CLOCK->TASKS_CTSTOP;
+    PRINTF( "TASKS_CTSTOP:    " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    //  HFCLK oscillator started
+    r0 = NRF_CLOCK->EVENTS_HFCLKSTARTED;
+    PRINTF( "EVENTS_HFCLKSTARTED:" );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // LFCLK oscillator started
+    r0 = NRF_CLOCK->EVENTS_LFCLKSTARTED;
+    PRINTF( "EVENTS_LFCLKSTARTED:" );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Calibration of LFCLK RC oscillator completed
+    r0 = NRF_CLOCK->EVENTS_DONE;
+    PRINTF( "EVENTS_DONE:     " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Calibration timer timeout
+    r0 = NRF_CLOCK->EVENTS_CTTO;
+    PRINTF( "EVENTS_CTTO:     " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Interrupt enable set register
+    r0 = NRF_CLOCK->INTENSET;
+    PRINTF( "INTENSET:        " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Interrupt enable clear register
+    r0 = NRF_CLOCK->INTENCLR;
+    PRINTF( "INTENCLR:        " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Task HFCLKSTART trigger status
+    r0 = NRF_CLOCK->HFCLKRUN;
+    PRINTF( "HFCLKRUN:        " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // high frequency clock status
+    r0 = NRF_CLOCK->HFCLKSTAT;
+    PRINTF( "HFCLKSTAT:       " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Task LFCLKSTART trigger status
+    r0 = NRF_CLOCK->LFCLKRUN;
+    PRINTF( "LFCLKRUN:        " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Low frequency clock status
+    r0 = NRF_CLOCK->LFCLKSTAT;
+    PRINTF( "LFCLKSTAT:       " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // lock source for the LFCLK clock
+    r0 = NRF_CLOCK->LFCLKSRCCOPY;
+    PRINTF( "LFCLKSRCCOPY:    " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Clock source for the LFCLK clock
+    r0 = NRF_CLOCK->LFCLKSRC;
+    PRINTF( "LFCLKSRC:        " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Calibration timer interval
+    r0 = NRF_CLOCK->CTIV;
+    PRINTF( "CTIV:            " );
+    reg_print(SIZE32, r0);
+    put_rn();
+    // Crystal frequency
+    r0 = NRF_CLOCK->XTALFREQ;
+    PRINTF( "XTALFREQ:        " );
+    reg_print(SIZE32, r0);
+    put_rn();
+}
+#endif  // USE_FREQ
+
+#if USE_PORT
+void port_all(void)
+{
+    uint32_t p0, p1;
+    uint8_t n;
+
+    put_r();
+    PRINTF( "GPIO registers" );
+    put_rn();
+    p0 = NRF_GPIO->OUTSET;
+    PRINTF( "OUT: " );
+    reg_print(SIZE32, p0);
+    PRINTF( " ;0=L, 1=H" );
+    put_rn();
+    p0 = NRF_GPIO->IN;
+    PRINTF( "IN:  " );
+    reg_print(SIZE32, p0);
+    PRINTF(" ;0=L, 1=H");
+    put_rn();
+    p0 = NRF_GPIO->DIRSET;
+    PRINTF("DIR: ");
+    reg_print(SIZE32, p0);
+    PRINTF(" ;0=in,1=out");
+    put_rn();
+    PRINTF("Dc=Disconnect,Cn=Connect,Ot=Out,Dis=Disabled,PU=Pullup,");
+    PRINTF("PD=Pulldown,Hi=High,Lo=Low");
+    for (n=0; n < 32; n++) {
+        put_rn();
+        p0 = NRF_GPIO->PIN_CNF[n];
+        PRINTF("P0_%02d: DIR=", n);
+        if (p0 & 0x1) {
+            PRINTF("Ot");
+        } else {
+            PRINTF("In");
+        }
+        PRINTF(", IN=");
+        if (p0 & 0x2) {
+            PRINTF("Dc");
+        } else {
+            PRINTF("Cn");
+        }
+        PRINTF(", PULL=");
+        p1 = (p0 >> 2) & 0x3;
+        switch (p1) {
+            case 0:
+                PRINTF("Dis");
+                break;
+            case 1:
+                PRINTF("PD ");
+                break;
+            case 3:
+                PRINTF("PU ");
+                break;
+            default:
+                PRINTF("?  ");
+                break;
+        }
+        PRINTF(", Drive=");
+        p1 = (p0 >> 8) & 0x7;
+        switch (p1) {
+            case 0:
+                PRINTF("S0S1");
+                break;
+            case 1:
+                PRINTF("H0S1");
+                break;
+            case 2:
+                PRINTF("S0H1");
+                break;
+            case 3:
+                PRINTF("H0H1");
+                break;
+            case 4:
+                PRINTF("D0S1");
+                break;
+            case 5:
+                PRINTF("D0H1");
+                break;
+            case 6:
+                PRINTF("S0D1");
+                break;
+            case 7:
+                PRINTF("H0D1");
+                break;
+            default:
+                PRINTF("?   ");
+                break;
+        }
+        PRINTF(", SENSE=");
+        p1 = (p0 >> 16) & 0x3;
+        switch (p1) {
+            case 0:
+                PRINTF("Dis");
+                break;
+            case 2:
+                PRINTF("Hi ");
+                break;
+            case 3:
+                PRINTF("Lo ");
+                break;
+            default:
+                PRINTF("?  ");
+                break;
+        }
+    }
+}
+#endif  // USE_PORT
+
+#if USE_UART
+void uart_reg(void)
+{
+    uint32_t p0, p1;
+
+    put_r();
+    PRINTF("Registers/UART");
+    put_rn();
+    p0 = NRF_UART0->ENABLE;
+    p1 = p0 & 0x7;
+    PRINTF("UART is ");
+    if (p1 == 4) {
+        PRINTF("enabled");
+        put_rn();
+        p0 = NRF_UART0->BAUDRATE;
+        switch(p0) {
+            case UART_BAUDRATE_BAUDRATE_Baud1200:
+                p1 = 1200;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud2400:
+                p1 = 2400;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud4800:
+                p1 = 4800;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud9600:
+                p1 = 9600;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud14400:
+                p1 = 14400;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud19200:
+                p1 = 19200;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud28800:
+                p1 = 28800;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud38400:
+                p1 = 38400;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud57600:
+                p1 = 576000;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud76800:
+                p1 = 76800;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud115200:
+                p1 = 115200;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud230400:
+                p1 = 230400;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud250000:
+                p1 = 250000;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud460800:
+                p1 = 460800;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud921600:
+                p1 = 921600;
+                break;
+            case UART_BAUDRATE_BAUDRATE_Baud1M:
+                PRINTF("Baud rate: 1M");
+                p1 = 1;
+                break;
+            default:
+                PRINTF("Baud rate: Unknown");
+                p1 = 0;
+        }
+        if (p1 > 10) {
+            PRINTF("Baud rate: %dbps", p1);
+        }
+        put_rn();
+        p0 = NRF_UART0->PSELTXD;
+        PRINTF("TXD Pin: ");
+        if (p0 == 0xffffffff) {
+            PRINTF("Unknown");
+        } else {
+            PRINTF("P0_%02d", p0);
+        }
+        put_rn();
+        p0 = NRF_UART0->PSELRXD;
+        PRINTF("RXD Pin: ");
+        if (p0 == 0xffffffff) {
+            PRINTF("Unknown");
+        } else {
+            PRINTF("P0_%02d", p0);
+        }
+        put_rn();
+        p0 = NRF_UART0->PSELRTS;
+        PRINTF("RTS Pin: ");
+        if (p0 == 0xffffffff) {
+            PRINTF("Unknown");
+        } else {
+            PRINTF("P0_%02d", p0);
+        }
+        put_rn();
+        p0 = NRF_UART0->PSELCTS;
+        PRINTF("CTS Pin: ");
+        if (p0 == 0xffffffff) {
+            PRINTF("Unknown");
+        } else {
+            PRINTF("P0_%02d", p0);
+        }
+#if SIMPLE_NOT_SHOW
+        put_rn();
+        p0 = NRF_UART0->SHORTS;
+        PRINTF("SHORTS:  ");
+        reg_print(SIZE32, p0);
+        put_rn();
+        p0 = NRF_UART0->ERRORSRC;
+        PRINTF("ERRORSRC:");
+        reg_print(SIZE32, p0);
+#endif
+    } else {
+        PRINTF("disabled");
+    }
+    put_rn();
+}
+#endif  //USE_UART
+
+#if USE_SPI
+void spi_reg(uint8_t n)
+{
+    uint32_t r0, r1, r2, r3;
+
+    put_r();
+    PRINTF("Registers/SPI");
+    put_rn();
+    if (n == 0) {
+        r0 = NRF_SPI0->ENABLE;
+        PRINTF("SPI0 is ");
+    } else {
+        r0 = NRF_SPI1->ENABLE;
+        PRINTF("SPI1 is ");
+    }
+    r1 = r0 & 0x7;
+    if (r1 == 1) {
+        PRINTF("enabled");
+        put_rn();
+        if (n == 0) {
+            r0 = NRF_SPI0->FREQUENCY;
+            r1 = NRF_SPI0->PSELMOSI;
+            r2 = NRF_SPI0->PSELMISO;
+            r3 = NRF_SPI0->PSELSCK;
+        } else {
+            r0 = NRF_SPI1->FREQUENCY;
+            r1 = NRF_SPI1->PSELMOSI;
+            r2 = NRF_SPI1->PSELMISO;
+            r3 = NRF_SPI1->PSELSCK;
+        }
+        PRINTF("Clock:");
+        switch(r0) {
+            case SPI_FREQUENCY_FREQUENCY_K125:
+                PRINTF("125k");
+                break;
+            case SPI_FREQUENCY_FREQUENCY_K250:
+                PRINTF("250k");
+                break;
+            case SPI_FREQUENCY_FREQUENCY_K500:
+                PRINTF("500k");
+                break;
+            case SPI_FREQUENCY_FREQUENCY_M1:
+                PRINTF("1M");
+                break;
+            case SPI_FREQUENCY_FREQUENCY_M2:
+                PRINTF("2M");
+                break;
+            case SPI_FREQUENCY_FREQUENCY_M4:
+                PRINTF("4M");
+                break;
+            case SPI_FREQUENCY_FREQUENCY_M8:
+                PRINTF("8M");
+                break;
+            default:
+                PRINTF("Unknown");
+        }
+        PRINTF("bps");
+        put_rn();
+        PRINTF("MOSI Pin: ");
+        if (r1 == 0xffffffff) {
+            PRINTF("Unknown");
+        } else {
+            PRINTF("P0_%02d", r1);
+        }
+        put_rn();
+        PRINTF("MISO Pin: ");
+        if (r2 == 0xffffffff) {
+            PRINTF("Unknown");
+        } else {
+            PRINTF("P0_%02d", r2);
+        }
+        put_rn();
+        PRINTF("SCK  Pin: ");
+        if (r3 == 0xffffffff) {
+            PRINTF("Unknown");
+        } else {
+            PRINTF("P0_%02d", r3);
+        }
+    } else {
+        PRINTF("disabled");
+    }
+    put_rn();
+}
+#endif  //USE_SPI
+
+#if USE_ADC
+#if 0
+void adc_reg(void)
+{
+    uint32_t r0, r1;
+
+    put_r();
+    PRINTF("Registers/ADC");
+    put_rn();
+    r0 = NRF_ADC->ENABLE;
+    r1 = r0 & 0x3;
+    if (r1 == 1) {
+        PRINTF("enabled");
+        put_rn();
+#if 1
+        put_rn();
+        PRINTF("RES   :  ");
+        reg_print(SIZE32, NRF_ADC->RES);
+        put_rn();
+        PRINTF("INPSEL:  ");
+        reg_print(SIZE32, NRF_ADC->INPSEL);
+        PRINTF("REFSEL:  ");
+        reg_print(SIZE32, NRF_ADC->REFSEL);
+        put_rn();
+        PRINTF("PSEL  :  ");
+        reg_print(SIZE32, NRF_ADC->PSEL);
+        PRINTF("EXTREFSEL:  ");
+        reg_print(SIZE32, NRF_ADC->EXTREFSEL);
+        put_rn();
+#endif
+    } else {
+        PRINTF("disabled");
+    }
+    put_rn();
+}
+#else
+
+#if 0
+TASKS_START;                       // Start an ADC conversion.                                              */
+TASKS_STOP;                        // Stop ADC.                                                             */
+EVENTS_END;                        // ADC conversion complete.                                              */
+INTENSET;                          // Interrupt enable set register.                                        */
+INTENCLR;                          // Interrupt enable clear register.                                      */
+BUSY;                              // ADC busy register.                                                    */
+ENABLE;                            // ADC enable.                                                           */
+CONFIG;                            // ADC configuration register.                                           */
+RESULT;                            // Result of ADC conversion.                                             */
+POWER;                             // Peripheral power control.
+#endif
+
+void adc_reg(void)
+{
+    uint32_t r0, r1;
+
+    put_r();
+    PRINTF("Registers/ADC");
+    put_rn();
+    PRINTF("TASKS_START:  ");
+    reg_print(SIZE32, NRF_ADC->TASKS_START);
+    put_rn();
+    PRINTF("TASKS_STOP :  ");
+    reg_print(SIZE32, NRF_ADC->TASKS_STOP);
+    put_rn();
+    PRINTF("EVENTS_END :  ");
+    reg_print(SIZE32, NRF_ADC->EVENTS_END);
+    put_rn();
+    PRINTF("INTENSET   :  ");
+    reg_print(SIZE32, NRF_ADC->INTENSET);
+    put_rn();
+    PRINTF("INTENCLR   :  ");
+    reg_print(SIZE32, NRF_ADC->INTENCLR);
+    put_rn();
+    PRINTF("BUSY       :  ");
+    reg_print(SIZE32, NRF_ADC->BUSY);
+    put_rn();
+    PRINTF("ENABLE     :  ");
+    reg_print(SIZE32, NRF_ADC->ENABLE);
+    put_rn();
+    PRINTF("CONFIG     :  ");
+    reg_print(SIZE32, NRF_ADC->CONFIG);
+    put_rn();
+    PRINTF("RESULT     :  ");
+    reg_print(SIZE32, NRF_ADC->RESULT);
+    put_rn();
+    PRINTF("POWER      :  ");
+    reg_print(SIZE32, NRF_ADC->POWER);
+    put_rn();
+    // judge each condition
+    r0 = NRF_ADC->ENABLE;
+    r1 = r0 & 0x3;
+    PRINTF("ADC is ");
+    if (r1 == 1) {
+        PRINTF("enabled");
+    } else {
+        PRINTF("disabled");
+    }
+    put_rn();
+    r0 = NRF_ADC->CONFIG;
+    r1 = r0 & 0x03;
+    PRINTF("Resolution : ");
+    if (r1 == 0) {
+        PRINTF("8bit");
+    } else if (r1 == 1) {
+        PRINTF("9bit");
+    } else if (r1 == 2) {
+        PRINTF("10bit");
+    }
+    put_rn();
+    r1 = (r0 & 0x1c) >> 2;
+    PRINTF("INPSEL: ");
+    switch (r1) {
+        case 0:
+            PRINTF("Pin specified by CONFIG.PSEL with no prescaling");
+            break;
+        case 1:
+            PRINTF("Pin specified by CONFIG.PSEL with 2/3 prescaling");
+            break;
+        case 2:
+            PRINTF("Pin specified by CONFIG.PSEL with 1/3 prescaling");
+            break;
+        case 5:
+            PRINTF("VDD with 2/3 prescaling");
+            break;
+        case 6:
+            PRINTF("VDD with 1/3 prescaling");
+            break;
+        default:
+            PRINTF("???");
+            break;
+    }
+    put_rn();
+    r1 = (r0 & 0x60) >> 6;
+    PRINTF("REFSEL: ");
+    switch (r1) {
+        case 0:
+            PRINTF("VBG // Use internal 1.2 V band gap reference");
+            break;
+        case 1:
+            PRINTF("External // Use external ");
+            PRINTF("reference specified by CONFIG. EXTREFSEL");
+            break;
+        case 2:
+            PRINTF("SupplyOneHalfPrescaling // Use VDD with 1/2 prescaling");
+            break;
+        case 3:
+            PRINTF("SupplyOneThirdPrescaling // Use VDD with 1/3 prescaling");
+            break;
+        default:
+            PRINTF("???");
+            break;
+    }
+    put_rn();
+    r1 = (r0 & 0xff00) >> 8;
+    PRINTF("PSEL: ");
+    switch (r1) {
+        case 0:
+            PRINTF("Disabled");
+            break;
+        case 1:
+            PRINTF("AnalogInput0");
+            break;
+        case 2:
+            PRINTF("AnalogInput1");
+            break;
+        case 4:
+            PRINTF("AnalogInput2");
+            break;
+        case 8:
+            PRINTF("AnalogInput3");
+            break;
+        case 16:
+            PRINTF("AnalogInput4");
+            break;
+        case 32:
+            PRINTF("AnalogInput5");
+            break;
+        case 64:
+            PRINTF("AnalogInput6");
+            break;
+        case 128:
+            PRINTF("AnalogInput7");
+            break;
+        default:
+            PRINTF("???");
+            break;
+    }
+    put_rn();
+}
+#endif
+#endif  //USE_ADC
+
+#if 0
+TASKS_STARTRX;  //Start 2-Wire master receive sequence
+TASKS_STARTTX;  //Start 2-Wire master transmit sequence
+TASKS_STOP;     //Stop 2-Wire transaction
+TASKS_SUSPEND;  //Suspend 2-Wire transaction
+TASKS_RESUME;   //Resume 2-Wire transaction
+EVENTS_STOPPED; //Two-wire stopped
+EVENTS_RXDREADY;//Two-wire ready to deliver new RXD byte received
+EVENTS_TXDSENT; //Two-wire finished sending last TXD byte
+EVENTS_ERROR;   //Two-wire error detected
+EVENTS_BB;      //Two-wire byte boundary
+EVENTS_SUSPENDED;//Two-wire suspended
+SHORTS;         //Shortcuts for TWI
+INTENSET;       //Interrupt enable set register
+INTENCLR;       //Interrupt enable clear register
+ERRORSRC;       //Two-wire error source. Write error field to 1 to clear error
+ENABLE;         //Enable two-wire master
+PSELSCL;        //Pin select for SCL
+PSELSDA;        //Pin select for SDA
+RXD;            //RX data register
+TXD;            //TX data register
+FREQUENCY;      //Two-wire frequency
+ADDRESS;// Address used in the two-wire transfer.                                */
+POWER;//Peripheral power control.
+#endif
+
+#if USE_I2C
+void i2c_reg(uint8_t n)
+{
+    uint32_t r0, r1, r2;
+#if SIMPLE_NOT_SHOW
+    uint32_t r3, r4;
+#endif
+
+    put_r();
+    PRINTF("Registers/TWI(I2C)");
+    put_rn();
+    if (n == 0) {
+        r0 = NRF_TWI0->ENABLE;
+        PRINTF("TWI0 is ");
+    } else {
+        r0 = NRF_TWI1->ENABLE;
+        PRINTF("TWI1 is ");
+    }
+    r1 = r0 & 0x7;
+    if (r1 == 5) {
+        PRINTF("enabled");
+        put_rn();
+        if (n == 0) {
+            r0 = NRF_TWI0->FREQUENCY;
+            r1 = NRF_TWI0->PSELSCL;
+            r2 = NRF_TWI0->PSELSDA;
+#if SIMPLE_NOT_SHOW
+            r3 = NRF_TWI0->SHORTS;
+            r4 = NRF_TWI0->ERRORSRC;
+#endif
+        } else {
+            r0 = NRF_TWI1->FREQUENCY;
+            r1 = NRF_TWI1->PSELSCL;
+            r2 = NRF_TWI1->PSELSDA;
+#if SIMPLE_NOT_SHOW
+            r3 = NRF_TWI1->SHORTS;
+            r4 = NRF_TWI1->ERRORSRC;
+#endif
+        }
+        PRINTF("Clock: ");
+        if (r0 == TWI_FREQUENCY_FREQUENCY_K100) {
+            PRINTF("100KHz");
+        } else if (p0 == TWI_FREQUENCY_FREQUENCY_K250) {
+            PRINTF("250KHz");
+        } else if (p0 == TWI_FREQUENCY_FREQUENCY_K400) {
+            PRINTF("400KHz");
+        } else {
+            PRINTF("Unknown");
+        }
+        put_rn();
+        PRINTF("SCL Pin: ");
+        if (r1 == 0xffffffff) {
+            PRINTF("Unknown");
+        } else {
+            PRINTF("P0_%02d", r1);
+        }
+        put_rn();
+        PRINTF("SDA Pin: ");
+        if (r2 == 0xffffffff) {
+            PRINTF("Unknown");
+        } else {
+            PRINTF("P0_%02d", r2);
+        }
+#if SIMPLE_NOT_SHOW
+        put_rn();
+        PRINTF("SHORTS:  ");
+        reg_print(SIZE32, r3);
+        put_rn();
+        PRINTF("ERRORSRC:");
+        reg_print(SIZE32, r4);
+#endif
+    } else {
+        PRINTF("disabled");
+    }
+    put_rn();
+}
+#endif  //USE_I2C
+
+#if USE_POWER
+void power_reg(void)
+{
+    put_r();
+    PRINTF("POWER Management");
+    put_rn();
+    // Enable low power mode (variable latency)
+    PRINTF("TASKS_CONSTLAT:");
+    reg_print(SIZE32, NRF_POWER->TASKS_CONSTLAT);
+    put_rn();
+    // Enable low power mode (variable latency)
+    PRINTF("TASKS_LOWPWR:  ");
+    reg_print(SIZE32, NRF_POWER->TASKS_LOWPWR);
+    put_rn();
+    // Power failure warning
+    PRINTF("EVENTS_POFWARN:");
+    reg_print(SIZE32, NRF_POWER->EVENTS_POFWARN);
+    put_rn();
+    // Interrupt enable set register
+    PRINTF("INTENSET:  ");
+    reg_print(SIZE32, NRF_POWER->INTENSET);
+    put_rn();
+    // Interrupt enable clear register
+    PRINTF("INTENCLR:  ");
+    reg_print(SIZE32, NRF_POWER->INTENCLR);
+    put_rn();
+    // Reset reason
+    PRINTF("RESETREAS: ");
+    reg_print(SIZE32, NRF_POWER->RESETREAS);
+    put_rn();
+    // Ram status register
+    PRINTF("RAMSTATUS: ");
+    reg_print(SIZE32, NRF_POWER->RAMSTATUS);
+    put_rn();
+    // System off register
+    PRINTF("SYSTEMOFF: ");
+    reg_print(SIZE32, NRF_POWER->SYSTEMOFF);
+    put_rn();
+    // Power failure configuration
+    PRINTF("POFCON:    ");
+    reg_print(SIZE32, NRF_POWER->POFCON);
+    put_rn();
+    // General purpose retention register
+    PRINTF("GPREGRET:  ");
+    reg_print(SIZE32, NRF_POWER->GPREGRET);
+    put_rn();
+    // Ram on/off
+    PRINTF("RAMON:     ");
+    reg_print(SIZE32, NRF_POWER->RAMON);
+    put_rn();
+    // Ram on/off
+    PRINTF("RAMONB:    ");
+    reg_print(SIZE32, NRF_POWER->RAMONB);
+    put_rn();
+    // DCDC converter enable configuration register
+    PRINTF("DCDCEN:    ");
+    reg_print(SIZE32, NRF_POWER->DCDCEN);
+    put_rn();
+    // DCDC power-up force register
+    PRINTF("DCDCFORCE: ");
+    reg_print(SIZE32, NRF_POWER->DCDCFORCE);
+    put_rn();
+}
+#endif  //USE_TIMER
+
+#if USE_POWER
+void timer_reg(uint8_t n)
+{
+    uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10;
+
+    put_r();
+    PRINTF("Registers/TIMER");
+    if (n == 0) {
+        r0 = NRF_TIMER0->SHORTS;
+        r1 = NRF_TIMER0->INTENSET;
+        r2 = NRF_TIMER0->INTENCLR;
+        r3 = NRF_TIMER0->MODE;
+        r4 = NRF_TIMER0->BITMODE;
+        r5 = NRF_TIMER0->PRESCALER;
+        r6 = NRF_TIMER0->CC[0];
+        r7 = NRF_TIMER0->CC[1];
+        r8 = NRF_TIMER0->CC[2];
+        r9 = NRF_TIMER0->CC[3];
+        r10 = NRF_TIMER0->POWER;
+        PRINTF("0");
+    } else if (n == 1) {
+        r0 = NRF_TIMER1->SHORTS;
+        r1 = NRF_TIMER1->INTENSET;
+        r2 = NRF_TIMER1->INTENCLR;
+        r3 = NRF_TIMER1->MODE;
+        r4 = NRF_TIMER1->BITMODE;
+        r5 = NRF_TIMER1->PRESCALER;
+        r6 = NRF_TIMER1->CC[0];
+        r7 = NRF_TIMER1->CC[1];
+        r8 = NRF_TIMER1->CC[2];
+        r9 = NRF_TIMER1->CC[3];
+        r10 = NRF_TIMER1->POWER;
+        PRINTF("1");
+    } else if (n == 2) {
+        r0 = NRF_TIMER2->SHORTS;
+        r1 = NRF_TIMER2->INTENSET;
+        r2 = NRF_TIMER2->INTENCLR;
+        r3 = NRF_TIMER2->MODE;
+        r4 = NRF_TIMER2->BITMODE;
+        r5 = NRF_TIMER2->PRESCALER;
+        r6 = NRF_TIMER2->CC[0];
+        r7 = NRF_TIMER2->CC[1];
+        r8 = NRF_TIMER2->CC[2];
+        r9 = NRF_TIMER2->CC[3];
+        r10 = NRF_TIMER2->POWER;
+        PRINTF("2");
+    } else {
+        return;
+    }
+    put_rn();
+    PRINTF("SHORTS:   ");
+    reg_print(SIZE32, r0);
+    put_rn();
+    PRINTF("INTENSET: ");
+    reg_print(SIZE32, r1);
+    put_rn();
+    PRINTF("INTENCLR: ");
+    reg_print(SIZE32, r2);
+    put_rn();
+    PRINTF("MODE:     ");
+    reg_print(SIZE32, r3);
+    put_rn();
+    PRINTF("BITMODE:  ");
+    reg_print(SIZE32, r4);
+    put_rn();
+    PRINTF("PRESCALER:");
+    reg_print(SIZE32, r5);
+    put_rn();
+    PRINTF("cc[0]: ");
+    reg_print(SIZE32, r6);
+    put_rn();
+    PRINTF("cc[1]: ");
+    reg_print(SIZE32, r7);
+    put_rn();
+    PRINTF("cc[2]: ");
+    reg_print(SIZE32, r8);
+    put_rn();
+    PRINTF("cc[3]: ");
+    reg_print(SIZE32, r9);
+    put_rn();
+    PRINTF("POWER: ");
+    reg_print(SIZE32, r10);
+    put_rn();
+}
+#endif  //USE_TIMER
+
+//------------------------------------------------------------------------------
+//  Monitor Main Program
+//------------------------------------------------------------------------------
+int mon_hw (void)
+{
+    char *ptr;
+
+    put_r();
+    PRINTF("%s [Help:'?' key]", mon_msg);
+    put_rn();
+    for (;;) {
+        put_r();
+        PUTC('>');
+        ptr = linebuf;
+        get_line(ptr, buf_size);
+        switch (*ptr++) {
+                //--------------------------------------------------------------
+                //    Memory
+                //--------------------------------------------------------------
+            case 'm' :
+#if USE_MEM
+                mem_inf(ptr);
+                put_rn();
+#else
+                not_select();
+#endif   // USE_MEM
+                break;
+                //--------------------------------------------------------------
+                //    POWER
+                //--------------------------------------------------------------
+            case 'w' :
+#if USE_POWER
+                power_reg();
+#else
+                not_select();
+#endif   // USE_POWER
+                break;
+                //--------------------------------------------------------------
+                //    Frequency(Clock)
+                //--------------------------------------------------------------
+            case 'f' :
+#if USE_FREQ
+                freq_reg();
+#else
+                not_select();
+#endif   // USE_FREQ
+                break;
+                //--------------------------------------------------------------
+                //    GPIO
+                //--------------------------------------------------------------
+            case 'p' :
+#if USE_PORT
+                port_all();
+                put_rn();
+#else
+                not_select();
+#endif   // USE_PORT
+                break;
+                //--------------------------------------------------------------
+                //    Register
+                //--------------------------------------------------------------
+            case 'r' :
+                uint8_t  r_flg;
+                put_r();
+                PRINTF("Reg. Mode u,i,s,t,a & ?");
+                put_rn();
+                r_flg = 0;
+                for (; r_flg != 0xff;) {
+                    PRINTF("r>");
+                    ptr = linebuf;
+                    get_line(ptr, buf_size);
+                    put_r();
+                    switch(*ptr++) {
+                        case 'u' :
+#if USE_UART
+                            uart_reg();
+#else
+                            not_select();
+#endif // USE_UART
+                            break;
+                        case 'i' :
+#if USE_I2C
+                            put_r();
+                            i2c_reg(0);
+                            put_rn();
+                            i2c_reg(1);
+#else
+                            not_select();
+#endif // USE_I2C
+                            break;
+                        case 's' :
+#if USE_SPI
+                            spi_reg(0);
+                            put_rn();
+                            spi_reg(1);
+#else
+                            not_select();
+#endif // USE_SPI
+                            break;
+                        case 't' :      //
+#if USE_TIMER
+                            timer_reg(0);
+                            put_rn();
+                            timer_reg(1);
+                            put_rn();
+                            timer_reg(2);
+#else
+                            not_select();
+#endif // USE_TIMER
+                            break;
+                        case 'a' :      //
+#if USE_ADC
+                            adc_reg();
+#else
+                            not_select();
+#endif // USE_SPI
+                            break;
+                        case 'q' :        // quit
+                            r_flg = 0xff;
+                            break;
+                        case '?' :
+                            PRINTF("u - UART");
+                            put_rn();
+                            PRINTF("i - I2C");
+                            put_rn();
+                            PRINTF("s - SPI");
+                            put_rn();
+                            PRINTF("t - TIMER");
+                            put_rn();
+                            PRINTF("a - ADC");
+                            put_rn();
+                            PRINTF("q - Exit mode");
+                            put_rn();
+                            break;
+                        default:
+                            PUTC('?');
+                            put_rn();
+                    }
+                }
+                PRINTF("Return to All Mode");
+                put_rn();
+                break;
+                //--------------------------------------------------------------
+                //    CPU
+                //--------------------------------------------------------------
+            case 'c' :    // CPU related information
+#if USE_SYS
+                put_r();
+                cpu_sys();
+#else
+                not_select();
+#endif   // USE_SYS
+                break;
+                //--------------------------------------------------------------
+                //    Help
+                //--------------------------------------------------------------
+            case '?' :
+                put_r();
+                msg_hlp_hw();
+                break;
+                //--------------------------------------------------------------
+                //    Return to main routine
+                //--------------------------------------------------------------
+            case 'q' :        // Quit
+                PRINTF("\rReturn to monitor ");
+                return 0;
+                //--------------------------------------------------------------
+                //    Special command for DEBUG
+                //--------------------------------------------------------------
+            case 'x' :
+                not_yet_impliment();
+                break;
+                //--------------------------------------------------------------
+                //    no support
+                //--------------------------------------------------------------
+            default:
+                PUTC('?');
+                put_rn();
+                break;
+        }
+    }
+}
+
+#endif  // defined(TARGET_NRF51822)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/9_Monitor/main.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,160 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2014 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.
+ */
+
+/*
+ *  Modified by Kenji Arai
+ *      http://www.page.sannet.ne.jp/kenjia/index.html
+ *      https://os.mbed.com/users/kenjiArai/
+ *
+ *      Started:    January    3rd, 2016
+ *      Revised:    Feburary  13th, 2016
+ *      Revised:    April     14th, 2018
+ */
+
+//#define EXAMPLE_9_MONITOR
+#ifdef EXAMPLE_9_MONITOR
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "BLE.h"
+#include "BatteryService.h"
+#include "nRF51_Vdd.h"
+#include "BME280.h"
+#include "TYBLE16_BASE.h"
+
+//  Definition -----------------------------------------------------------------
+/* Set this if you need debug messages on the console;
+ * it will have an impact on code-size and power consumption.
+ */
+#define NEED_CONSOLE_OUTPUT     1
+
+#if NEED_CONSOLE_OUTPUT
+#define DEBUG(...) { pc.printf(__VA_ARGS__); }
+#else
+#define DEBUG(...) /* nothing */
+#endif /* #if NEED_CONSOLE_OUTPUT */
+
+//  Object ---------------------------------------------------------------------
+DigitalOut  led1(LED1, 1);
+DigitalIn   sw(BUTTON1);
+AnalogIn    ana0(A0);
+DigitalIn   sw1(A1);
+Serial      pc(USBTX, USBRX);
+I2C         i2c(I2C_SDA, I2C_SCL);
+BME280      hmtp(i2c);
+SPI         spi(SPI_PSELMOSI0, SPI_PSELMISO0, SPI_PSELSCK0);
+nRF51_Vdd   vdd(3.6f, 2.6f);
+Ticker      t;
+
+//  ROM / Constant data --------------------------------------------------------
+const char *deviceName = "mbedMon";
+char *const opngmsg =
+    "\x1b[2J\x1b[H"__FILE__ "\r\n"__DATE__ " " __TIME__ " (UTC)\r\n""\r\n";
+
+//  RAM ------------------------------------------------------------------------
+BatteryService *batteryService = NULL;
+uint8_t batteryLevel = 50;
+
+//  Function prototypes --------------------------------------------------------
+extern void debug_interface(uint8_t mode);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+void disconnectionCallback
+(const Gap::DisconnectionCallbackParams_t *disconnectionParams)
+{
+    DEBUG("Disconnected handle %u!\n\r", disconnectionParams->handle);
+    DEBUG("Restarting the advertising process\n\r");
+    // restart advertising
+    BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
+}
+
+void blink(void)
+{
+    led1 = !led1;
+}
+
+int main(void)
+{
+    // ******************************************************
+    // Here is a example to impliment the monitor
+    // para: 1 -> goto montor and never comeback
+    // ******************************************************
+#if 0
+    debug_interface(1);
+#endif
+
+    pc.puts(opngmsg);
+    // Application program runs at here
+    t.attach(blink, 1.0f);
+
+    DEBUG("Initialising the nRF5x chip\r\n");
+
+    // Check TYBLE-16 configuration
+    cpu_sys();
+    compile_condition();
+    //
+    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
+    ble.init();
+    ble.setDeviceName((const uint8_t *)deviceName);
+    ble.onDisconnection(disconnectionCallback);
+
+    batteryService = new BatteryService(ble, batteryLevel);
+
+    /* setup advertising */
+    ble.accumulateAdvertisingPayload
+    (GapAdvertisingData::BREDR_NOT_SUPPORTED |
+     GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
+                                     (const uint8_t *)deviceName,
+                                     strlen(deviceName));
+    ble.setAdvertisingInterval(1000); /* 1000ms; in multiples of 0.625ms. */
+    ble.startAdvertising();
+
+    while (true) {
+        // this will return upon any system event
+        ble.waitForEvent();
+
+        // the magic battery processing
+        batteryLevel++;
+#if 1
+        if (batteryLevel > 100) {
+            batteryLevel = 20;
+        }
+        DEBUG("Vdd: %4.3f\r\n", vdd.read_real_value());
+#else
+        DEBUG("Vdd: %f\r\n", vdd.read_real_value());
+        batteryLevel = vdd.read();
+#endif
+
+        batteryService->updateBatteryLevel(batteryLevel);
+        DEBUG("battery=%d\r\n", batteryLevel);
+
+        DEBUG("analog input = %f\r\n", ana0.read());
+        DEBUG("Temperature= %+5.2f [degC]\r\n", hmtp.getTemperature());
+
+        // ******************************************************
+        // Here is a example to impliment the monitor
+        // para: 0 -> if Uart RX Data is ready then goto montor
+        // ******************************************************
+        debug_interface(0);
+        Thread::wait(1000);
+    }
+}
+
+#endif
--- a/TYBLE16_os5_BASE.lib	Tue Apr 10 12:43:29 2018 +0000
+++ b/TYBLE16_os5_BASE.lib	Sat Apr 14 04:56:34 2018 +0000
@@ -1,1 +1,1 @@
-https://os.mbed.com/users/kenjiArai/code/TYBLE16_os5_BASE/#d626609f0029
+https://os.mbed.com/users/kenjiArai/code/TYBLE16_os5_BASE/#3a1ceeab2e20
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/BME280.lib	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/MACRUM/code/BME280/#c1f1647004c4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/TextLCD.lib	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/wim/code/TextLCD/#111ca62e8a59
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/nRF51_Vdd.lib	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/users/kenjiArai/code/nRF51_Vdd/#faf2e448c15b
--- a/main.cpp	Tue Apr 10 12:43:29 2018 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Mbed Application program / Blinky
- *
- * Copyright (c) 2018 Kenji Arai / JH1PJL
- *  http://www.page.sannet.ne.jp/kenjia/index.html
- *  http://mbed.org/users/kenjiArai/
- *      Created:    April     10th, 2018
- *      Revised:    April     10th, 2018
- */
- 
-//  Include --------------------------------------------------------------------
-#include "mbed.h"
-#include "TYBLE16_BASE.h"
-
-//  Definition -----------------------------------------------------------------
-
-//  Constructor ----------------------------------------------------------------
-DigitalOut  my_led(LED1);
-Serial      pc(USBTX, USBRX);
- 
-//  RAM ------------------------------------------------------------------------
- 
-//  ROM / Constant data --------------------------------------------------------
-char *const opngmsg =
-    "\x1b[2J\x1b[H"__FILE__ "\r\n"__DATE__ " " __TIME__ " (UTC)\r\n""\r\n";
-
-//  Function prototypes --------------------------------------------------------
- 
-//------------------------------------------------------------------------------
-//  Control Program
-//------------------------------------------------------------------------------
-int main()
-{
-    uint32_t count = 0;
-
-    pc.puts(opngmsg);
-    // Check TYBLE-16 configuration
-    cpu_sys();
-    compile_condition();
-    while(true) {
-        my_led = !my_led;
-        pc.printf("%8u\r\n", count++);
-        Thread::wait(1000);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/select_example.cpp	Sat Apr 14 04:56:34 2018 +0000
@@ -0,0 +1,94 @@
+/*
+ * AE-TYBLE16 Module example programs
+ *
+ * Copyright (c) 2018 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    April      7th, 2018
+ *      Revised:    April     14th, 2018
+ */
+
+/*
+    You can select several examples as followings.
+    0.  0_Blinky_LED
+        LED Blinky
+    1.  1_Check_RTC
+        Check RTC function
+        -> Time is not so accurate because 32.768KHz is made by Internal RC osc.
+    2.  2_EddyStoneBeacon
+        Demonstration sample program EddyStone Beacon
+    3.  3_Heart_Rate
+        Demonstration sample program Heart Rate
+    4.  4_RCBController
+        Potential usage for Radio Controller (RCB Controller)
+    5.  5_SDCard
+        Demonstration sample program SD Card
+    6.  6_Thermo
+        Demonstration sample program Thermometer
+        -> If you have I2C temperature sensor, you can connect it.
+        -> LCD can display the data.
+    7 & 8.  7_Uart_Client & 8_Uart_Server
+        Uart Client(Central) and Server(Peripheral)
+        -> PLEASE SET VCOM BAUDRATE IS 115200
+    9.  9_Monitor
+        Check nRF51 CPU functions
+ */
+#define EXAMPLE_NUMBER      9
+// select 0 to 9
+
+//----------------- You don't need any modification ----------------------------
+#if EXAMPLE_NUMBER == 0
+#define EXAMPLE_0_BLINKY_LED
+#ifdef EXAMPLE_0_BLINKY_LED
+#include "0_Blinky_LED/main.cpp"
+#endif
+#elif EXAMPLE_NUMBER == 1
+#define EXAMPLE_1_CHECK_RTC
+#ifdef EXAMPLE_1_CHECK_RTC
+#include "1_Check_RTC/main.cpp"
+#endif
+#elif EXAMPLE_NUMBER == 2
+#define EXAMPLE_2_EDDYSTONE_BEACON
+#ifdef EXAMPLE_2_EDDYSTONE_BEACON
+#include "2_EddyStoneBeacon/main.cpp"
+#endif
+#elif EXAMPLE_NUMBER == 3
+#define EXAMPLE_3_HEART_RATE
+#ifdef EXAMPLE_3_HEART_RATE
+#include "3_Heart_Rate/main.cpp"
+#endif
+#elif EXAMPLE_NUMBER == 4
+#define EXAMPLE_4_RCB_CONTROLLER
+#ifdef EXAMPLE_4_RCB_CONTROLLER
+#include "4_RCBController/main.cpp"
+#endif
+#elif EXAMPLE_NUMBER == 5
+#define EXAMPLE_5_SDCARD
+#ifdef EXAMPLE_5_SDCARD
+#include "5_SDCard/main.cpp"
+#endif
+#elif EXAMPLE_NUMBER == 6
+#define EXAMPLE_6_THERMO
+#ifdef EXAMPLE_6_THERMO
+#include "6_Thermo/main.cpp"
+#endif
+#elif EXAMPLE_NUMBER == 7
+#define EXAMPLE_7_UART_CLIENT
+#ifdef EXAMPLE_7_UART_CLIENT
+#include "7_Uart_Client/main.cpp"
+#warning "Please set VCOM baudrate -> 115200 ""
+#endif
+#elif EXAMPLE_NUMBER == 8
+#define EXAMPLE_8_UART_SERVER
+#ifdef EXAMPLE_8_UART_SERVER
+#include "8_Uart_Server/main.cpp"
+#warning "Please set VCOM baudrate -> 115200 ""
+#endif
+#elif EXAMPLE_NUMBER == 9
+#define EXAMPLE_9_MONITOR
+#ifdef EXAMPLE_9_MONITOR
+#include "9_Monitor/main.cpp"
+#endif
+#else
+#error " Please set 0 to 9 number for EXAMPLE_NUMBER!!"
+#endif