The firmware of the Grove Node

Dependencies:   BLE_API color_pixels mbed-src-nrf51822 nRF51822

Fork of BLE_LoopbackUART by Bluetooth Low Energy

Revision:
9:84cb66d0375d
Parent:
6:e0fc9072e853
Child:
10:f34ff4e47741
--- a/main.cpp	Tue Sep 30 02:20:59 2014 +0000
+++ b/main.cpp	Thu Nov 06 02:22:01 2014 +0000
@@ -16,27 +16,60 @@
 
 #include "mbed.h"
 #include "BLEDevice.h"
-
+#include "DFUService.h"
 #include "UARTService.h"
+#include "nrf_delay.h"
+#include "battery.h"
 
-#define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console;
-                               * it will have an impact on code-size and power consumption. */
+#define DEBUG   0
+
+#if DEBUG       // for Arch BLE
+#define LOG(...)        { printf(__VA_ARGS__); }
+#define BUTTON_DOWN     1
+#define LED_ON          1
+#define LED_OFF         0
 
-#if NEED_CONSOLE_OUTPUT
-#define DEBUG(...) { printf(__VA_ARGS__); }
-#else
-#define DEBUG(...) /* nothing */
-#endif /* #if NEED_CONSOLE_OUTPUT */
+DigitalOut  blue(p30);
+DigitalOut  green(p17);
+InterruptIn button(p5);
+#else           // for Grove Node BLE
+#define LOG(...)
+#define BUTTON_DOWN     0
+#define LED_ON          0
+#define LED_OFF         1
+
+DigitalOut  blue(p18);
+DigitalOut  green(p17);
+InterruptIn button(p30);
+#endif
+
+Battery battery(p5);
 
 BLEDevice  ble;
-DigitalOut led1(LED1);
+UARTService *uartServicePtr;
+Ticker ticker;
+
+volatile bool button_event = false;
+
+const int MAX_ARGS = 8;
+char *argv[MAX_ARGS];
 
-UARTService *uartServicePtr;
+static const uint8_t SIZEOF_TX_RX_BUFFER = 32;
+uint8_t rxPayload[SIZEOF_TX_RX_BUFFER] = {0,};
+
+extern "C" void power_on();
+extern "C" void power_off();
+
+extern void node_init();
+extern void node_tick();
+extern void node_parse(int argc, char *argv[]);
+
+int button_detect();
 
 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
 {
-    DEBUG("Disconnected!\n\r");
-    DEBUG("Restarting the advertising process\n\r");
+    LOG("Disconnected!\n");
+    LOG("Restarting the advertising process\n");
     ble.startAdvertising();
 }
 
@@ -44,23 +77,53 @@
 {
     if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) {
         uint16_t bytesRead = params->len;
-        DEBUG("received %u bytes\n\r", bytesRead);
-        ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead);
+        LOG("received %u bytes\n\r", bytesRead);
+        if (bytesRead < sizeof(rxPayload)) {
+            memcpy(rxPayload, params->data, bytesRead);
+            rxPayload[bytesRead] = '\0';
+        }
+        
+        LOG("%s\n", (char *)rxPayload);
+
+        char *piece = strtok((char *)rxPayload, " ");
+        int argc = 0;
+        while (piece && argc < MAX_ARGS) {
+            argv[argc++] = piece;
+            piece = strtok(0, " ");
+        }
+        
+        if (argc > 0) {
+           node_parse(argc, argv);
+        }
+        
     }
 }
 
-void periodicCallback(void)
+void tick(void)
 {
-    led1 = !led1;
+    node_tick();
+}
+
+void button_down(void)
+{
+    button_event = true;
 }
 
 int main(void)
 {
-    led1 = 1;
-    Ticker ticker;
-    ticker.attach(periodicCallback, 1);
+    power_on();
+    blue = LED_ON;
+    green = LED_ON;
+    
+#if BUTTON_DOWN
+    button.mode(PullDown);
+    button.rise(button_down);
+#else
+    button.mode(PullUp);
+    button.fall(button_down);
+#endif
 
-    DEBUG("Initialising the nRF51822\n\r");
+    LOG("Initialising the nRF51822\n");
     ble.init();
     ble.onDisconnection(disconnectionCallback);
     ble.onDataWritten(onDataWritten);
@@ -69,17 +132,97 @@
     ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
     ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
     ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
-                                     (const uint8_t *)"BLE UART", sizeof("BLE UART") - 1);
+                                     (const uint8_t *)"NODE", sizeof("NODE"));
     ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                      (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
 
-    ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
-    ble.startAdvertising();
+    DFUService dfu(ble);
 
     UARTService uartService(ble);
     uartServicePtr = &uartService;
+    
+    ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
+    ble.startAdvertising();
+    
+    node_init();
+    ticker.attach(tick, 1);
 
+    blue = LED_OFF;
+    green = LED_OFF;
+    
     while (true) {
-        ble.waitForEvent();
+        if (button_event) {
+            int click;
+            
+            green = LED_ON;
+            click = button_detect();
+            green = LED_OFF;
+            LOG("click type: %d\n\r", click);
+            
+            button_event = false;
+            
+            if (1 == click) {
+            } else if (2 == click) {
+                //green = LED_ON;
+            } else if (-1 == click) {
+                green = LED_OFF;
+                blue = LED_OFF;
+                while (BUTTON_DOWN == button.read()) {
+                    
+                }
+                nrf_delay_us(3000);
+                
+                power_off();
+            } else {
+                continue;
+            }
+
+        } else {
+            ble.waitForEvent();
+        }
     }
 }
+
+int button_detect(void)
+{
+    int t = 0;
+    
+    while (1) {
+        if (button.read() != BUTTON_DOWN) {
+            if (t < 30) {
+                return 0;     // for anti shake
+            } else {
+                break;
+            }
+        }
+        
+        if (t > 30000) {        // More than 3 seconds
+            return -1;          // long click
+        }
+        
+        t++;
+        nrf_delay_us(100);
+    }
+    
+    if (t > 4000) {             // More than 0.4 seconds
+        return 1;               // single click
+    }
+    
+    while (true) {
+        if (button.read() == BUTTON_DOWN) {
+            nrf_delay_us(1000);
+            if (button.read() == BUTTON_DOWN) {
+                return 2;      // double click
+            }
+            
+            t += 10;
+        }
+        
+        if (t > 4000) {
+            return 1;          // The interval of double click should less than 0.4 seconds, so it's single click
+        }
+        
+        t++;
+        nrf_delay_us(100);
+    }
+}