ver1.0

Dependencies:   RingBuffer

Files at this revision

API Documentation at this revision

Comitter:
noboruk
Date:
Wed Feb 07 19:54:56 2018 +0000
Commit message:
ver1.0

Changed in this revision

RingBuffer.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 82eed72bc4e4 RingBuffer.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RingBuffer.lib	Wed Feb 07 19:54:56 2018 +0000
@@ -0,0 +1,1 @@
+http://os.mbed.com/users/ykuroda/code/RingBuffer/#ea6d02ba96ae
diff -r 000000000000 -r 82eed72bc4e4 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Feb 07 19:54:56 2018 +0000
@@ -0,0 +1,437 @@
+/*
+ *  ------- 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
+ *      http://mbed.org/users/kenjiArai/
+ *
+ *      Started:  April     8th, 2016
+ *      Revised:  June     13th, 2016
+ *      Revised:  October  22nd, 2017   Run on mbed-OS-5.6.2
+ *
+ *  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
+ *  Tested Server Device:
+ *      BLE_Uart_Server
+ *      https://developer.mbed.org/users/kenjiArai/code/BLE_Uart_Server/
+ */
+
+// 2018/02/07 太陽誘電 EYSGCNZWY 使用の試作機向けに改造
+
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "BLE.h"
+#include "UARTService.h"
+#include "ble/DiscoveredCharacteristic.h"
+#include "ble/DiscoveredService.h"
+#include "RingBuffer.h"
+
+//  Definition -----------------------------------------------------------------
+#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
+
+#define LED1_PIN    P0_25
+#define LED2_PIN    P0_23
+#define LED3_PIN    P0_21
+#define EXT_OUT_PIN P0_9
+#define ROM_CS_PIN  P0_12
+#define ROM_SCK_PIN P0_13
+#define ROM_SDI_PIN P0_15
+
+//  Object ---------------------------------------------------------------------
+DigitalOut  alivenessLED(LED1_PIN,1);
+DigitalOut  connectedLED(LED2_PIN,1);
+DigitalOut  out_led(LED3_PIN,1);
+DigitalOut  out_oc(EXT_OUT_PIN,0);     //オープンコレクタ出力
+//
+// UARTの端子ははEEPROMの端子を流用
+DigitalOut      dummy_cs(ROM_CS_PIN,1); //Disable Chip
+Serial          pc(ROM_SDI_PIN,ROM_SCK_PIN, 19200);    //SDI=TXD,SCK=RXD
+
+// Object
+BLE         ble;
+Ticker      ticker;
+Ticker      out_port_ticker;
+RingBuffer  ser_bf(1536);
+Thread      tsk;
+
+//  ROM / Constant data --------------------------------------------------------
+//#warning "You need to modify below value based on your board."
+//const Gap::Address_t    mac_board_0   = {0xae,0x2f,0x0d,0x6b,0x49,0xea};
+//
+const char PEER_NAME[] = "UART_S";
+//
+//  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;
+//
+bool            out_port_flag           = 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);
+void out_port_ticker_Callback(void);
+//      serial receiving
+void pc_ser_rx(void);
+void preparation_sending_data(void);
+//      Pre-check
+void adjust_line(uint8_t *);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+int main(void)
+{
+    dummy_cs = 1;
+    out_oc = 0;
+    alivenessLED = 1;
+    connectedLED = 1;
+    out_led = 1;
+
+    pc.attach(&serialRxCallback, Serial::RxIrq);
+    ticker.attach(periodicCallback, 1);
+    tsk.start(pc_ser_rx);
+
+    // clear terminal output
+    for (int k = 0; k < 5; k++) { pc.printf("\r\n");}
+
+    // opening message
+    pc.printf("UART Communication / Central side\r\n");
+    pc.printf("  need Peripheral module (run BLE_Peripheral_EYSGCNZWY program)\r\n"); 
+
+    // Mixed role **************************************************************
+    ble.init();
+    ble.gap().onConnection(connectionCallback);
+    ble.gap().onDisconnection(disconnectionCallback);
+
+    // Client(Central) role ****************************************************
+    ble.gattClient().onHVX(onReceivedDataFromDeviceCallback);
+    ble.gap().setScanParams(500, 450);
+    ble.gap().startScan(advertisementCallback);
+
+    while(true)
+    {
+        // allow notifications from Peripheral
+        if (foundUartRXCharacteristic &&
+            !ble.gattClient().isServiceDiscoveryActive())
+        {
+            // need to do the following only once
+            foundUartRXCharacteristic = false;
+            uint16_t value = BLE_HVX_NOTIFICATION;
+            ble.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.waitForEvent();
+    }
+}
+
+
+void periodicCallback(void)
+{
+    // Do blinky on alivenessLED to indicate system aliveness
+    alivenessLED = !alivenessLED; 
+    if (connected2server){
+        connectedLED = 0;
+    } else {
+        connectedLED = 1;
+    }
+    if (rx_isr_busy == true){
+        rx_isr_busy = false;
+    } else {
+        tsk.signal_set(0x01);
+    }
+}
+
+void out_port_ticker_Callback(void)
+{
+    out_led = 1;
+    out_oc = 0;
+    out_port_ticker.detach();   //
+}
+
+void serialRxCallback()
+{
+    ser_bf.save(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.check() == 0){
+            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.check() != 0){
+            char c = ser_bf.read();
+            if (c == '\b'){
+                linebf_irq_len--;
+                pc.putc(c);
+                pc.putc(' ');
+                pc.putc(c);
+            } else if ((c >= ' ') || (c == '\r') || (c == '\n')){
+                bool overflow = false;
+                if ((c == '\r') || (c == '\n')) {
+                    if (linebf_irq_len == NUM_ONCE - 1){// remain only 1 buffer
+                        overflow = true;
+                        linebf_irq[linebf_irq_len++] = '\r';
+                        pc.putc('\r');
+                    } else {
+                        overflow = false;
+                        linebf_irq[linebf_irq_len++] = '\r';
+                        linebf_irq[linebf_irq_len++] = '\n';
+                        pc.printf("\r\n");
+                    }
+                } else {
+                    linebf_irq[linebf_irq_len++] = c;
+                    pc.putc(c);
+                }
+                if (linebf_irq_len >= NUM_ONCE ){
+                    linebf_irq[linebf_irq_len] = 0;
+                    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;
+            // 0.5s port ON
+            out_led = 0;
+            out_oc = 1;
+            out_port_ticker.attach(out_port_ticker_Callback, 0.5);
+         }
+    }
+}
+
+
+// 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, 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
+                );
+                name_match = true;
+                break;
+            }
+        }
+        i += record_length;
+    }    
+    if( name_match != true ){ return; }
+
+    pc.printf("Found device : %s\r\n",PEER_NAME);
+    // connections
+    ble.gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+
+}
+
+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.gattClient().onServiceDiscoveryTermination(
+                discoveryTerminationCallback);
+        ble.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 Sever(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.startAdvertising();                         // restart advertising
+    } else {
+        ble.gap().startScan(advertisementCallback);     // restart scan
+    }
+}
+
+
diff -r 000000000000 -r 82eed72bc4e4 mbed-os.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Wed Feb 07 19:54:56 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#6e0d01cd13e8aca7bf4d697c3699ec9225386881