ver1.0

Dependencies:   RingBuffer

Revision:
0:7a3c39a4007a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Feb 07 19:53:44 2018 +0000
@@ -0,0 +1,482 @@
+/* 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
+ *      http://mbed.org/users/kenjiArai/
+ *
+ *      Started:  March     7th, 2016
+ *      Revised:  June     13th, 2016
+ *      Revised:  October  22nd, 2017   Run on mbed-OS-5.6.2
+ *
+ *  Original program:
+ *      BLE_LoopbackUART
+ *      https://developer.mbed.org/teams/Bluetooth-Low-Energy/
+ *                                  code/BLE_LoopbackUART/
+ *  Tested Controller Device:
+ *      BLE_Uart_Client
+ *      https://developer.mbed.org/users/kenjiArai/code/BLE_Uart_Client/
+ */
+
+// 2018/02/07 太陽誘電 EYSGCNZWY 使用の試作機向けに改造
+
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "BLE.h"
+#include "UARTService.h"
+#include "RingBuffer.h"
+
+//  Definition -----------------------------------------------------------------
+#define     NUM_ONCE            20
+#define     BFSIZE              (NUM_ONCE+4)
+
+// If you set 1, you need to connected LED1 and P_0
+// Please refer nRF51_WakeUP library
+#define     GOTO_SLEEP_MODE     0   
+                 
+//#define    USE_DEBUG_MODE
+#ifdef USE_DEBUG_MODE
+#define DEBUG(...) { printf(__VA_ARGS__); }
+#else
+#define DEBUG(...)
+#endif
+
+#define LED1_PIN    P0_25
+#define LED2_PIN    P0_23
+#define LED3_PIN    P0_21
+#define EXT_SW_PIN  P0_11
+#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);
+DigitalIn       external_sw(EXT_SW_PIN);
+//
+// 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;
+UARTService     *uartServicePtr;
+Ticker          ticker;
+Ticker          switch_read_ticker;
+RingBuffer      ser_bf(1024);
+Thread          tsk;
+Mutex           bletx_mutex;
+
+//  ROM / Constant data --------------------------------------------------------
+//#warning "You need to confirm your device name."
+const static char DEVICE_NAME[] = "UART_S";
+
+//  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;
+//
+bool            sw_now;
+bool            sw_old;
+uint16_t        push_cnt = 0;
+
+//  Function prototypes --------------------------------------------------------
+//      BLE
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *);
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params);
+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);
+int  xatoi (char **, int32_t *);
+void adjust_line(uint8_t *);
+//      Interrupt related
+void serialRxCallback(void);
+void periodicCallback(void);
+void switch_tickerCallback(void);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+int main(void)
+{
+    connectedLED = 1;
+    out_led = 1;
+    dummy_cs = 1;
+    sw_now = !external_sw;
+    sw_old = sw_now;
+
+    pc.attach(&serialRxCallback, Serial::RxIrq);
+    ticker.attach(periodicCallback, 1);
+    switch_read_ticker.attach(switch_tickerCallback, 0.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 / Peripheral side\r\n");
+    pc.printf("  need Central module (run BLE_Central_EYSGCNZWY program)\r\n");
+
+    ble.init();
+    Gap::AddressType_t my_mac_type;
+    ble.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_MAC 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]
+    );
+
+    ble.onDisconnection(disconnectionCallback);
+    ble.onConnection(connectionCallback);
+    ble.onDataWritten(onDataWritten_action);
+
+    /* setup advertising */
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.accumulateAdvertisingPayload(
+        GapAdvertisingData::COMPLETE_LOCAL_NAME,
+        (const uint8_t *)DEVICE_NAME,
+        sizeof(DEVICE_NAME)
+    );
+    ble.accumulateAdvertisingPayload(
+        GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
+        (const uint8_t *)UARTServiceUUID_reversed,
+         sizeof(UARTServiceUUID_reversed)
+    );
+
+    // Advertize Interval
+    ble.setAdvertisingInterval(1000); /* 1000ms; in multiples of 0.625ms. */
+
+    // Start
+    ble.startAdvertising();
+    UARTService uartService(ble);
+    uartServicePtr = &uartService;
+    while(true){
+        if (time_out){
+        }
+        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.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){
+            default:
+                //pc.printf("\r\nStep(%u)\r\n", __LINE__);
+                break;
+        }
+    }
+}
+
+void periodicCallback(void)
+{
+    if (rx_isr_busy == true){
+        rx_isr_busy = false;
+    } else {
+        tsk.signal_set(0x01);
+    }
+    alivenessLED = !alivenessLED; 
+}
+
+void switch_tickerCallback(void)
+{
+    sw_old = sw_now;
+    sw_now = !external_sw;
+    if( sw_now )
+    {
+        out_led = 0;
+    }
+    else
+    {
+        out_led = 1;
+    }
+    if( ( sw_now != sw_old ) && ( sw_now ) )
+    {
+        // push triger
+        push_cnt++;
+        sprintf((char *)tx_buf,"%04X\r\n",push_cnt);
+        tx_len = strlen((const char *)tx_buf); 
+        Update_Values();
+    }
+}
+
+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;
+                bletx_mutex.lock();
+                ble.updateCharacteristicValue(
+                    uartServicePtr->getRXCharacteristicHandle(),
+                    linebf_irq,
+                    NUM_ONCE
+                );
+                bletx_mutex.unlock();
+            }
+        }
+        while(ser_bf.check() != 0){
+            char c = ser_bf.read();
+            if (c == '\b'){
+                linebf_irq_len--;
+                pc.putc(c);
+                pc.putc(' ');
+                pc.putc(c);
+            } else if ((c >= ' ') || (c == '\r') || (c == '\n')){
+                bool overflow = false;
+                if ((c == '\r') || (c == '\n')) {
+                    if (linebf_irq_len == NUM_ONCE - 1){// remain only 1 buffer
+                        overflow = true;
+                        linebf_irq[linebf_irq_len++] = '\r';
+                        pc.putc('\r');
+                    } else {
+                        overflow = false;
+                        linebf_irq[linebf_irq_len++] = '\r';
+                        linebf_irq[linebf_irq_len++] = '\n';
+                        pc.printf("\r\n");
+                    }
+                } else {
+                    linebf_irq[linebf_irq_len++] = c;
+                    pc.putc(c);
+                }
+                if (linebf_irq_len >= NUM_ONCE ){
+                    linebf_irq[linebf_irq_len] = 0;
+                    adjust_line(linebf_irq);
+                    linebf_irq_len = 0;
+                    bletx_mutex.lock();
+                    ble.updateCharacteristicValue(
+                        uartServicePtr->getRXCharacteristicHandle(),
+                        linebf_irq,
+                        NUM_ONCE
+                    );
+                    bletx_mutex.unlock();
+                    if (overflow == true){
+                        overflow = false;
+                        linebf_irq[linebf_irq_len++] = '\n';
+                        pc.putc('\n');
+                    }
+                }
+            }
+        }
+    }
+}
+
+void adjust_line(uint8_t *bf)
+{
+    uint8_t i, c;
+
+    for (i = 0; i <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_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();
+}
+
+//  Change string -> integer
+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;
+}
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
+{
+    DEBUG("Disconnected!\r\n");
+    DEBUG("Restarting the advertising process\r\n");
+    ble.startAdvertising();
+    connectedLED = 1;
+}
+
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
+{
+    DEBUG("Connected!\r\n");
+    connectedLED = 0;
+}
+
+void Update_Values(void)
+{
+    bletx_mutex.lock();
+    ble.updateCharacteristicValue(
+        uartServicePtr->getRXCharacteristicHandle(),
+        tx_buf,
+        tx_len
+    );
+    bletx_mutex.unlock();
+    tx_len = 0;
+}