BLE-writeable Display Puck with an e-paper display. Built on the Puck IOT platform.

Dependencies:   Puck lz mbed seeedstudio-epaper

The Display puck is a puck with an e-paper display that can show arbitrary black and white images received over Bluetooth LE.

A tutorial for the Display Puck is available on GitHub.

Tutorials and in-depth documentation for the Puck platform is available at the project's GitHub page

Files at this revision

API Documentation at this revision

Comitter:
sigveseb
Date:
Tue Jul 29 14:03:29 2014 +0000
Parent:
2:ea2c1ab55f20
Child:
4:cfb711a2c71f
Commit message:
Update display puck to use new puck lib

Changed in this revision

BLE_API.lib Show diff for this revision Revisions of this file
Puck.lib Show annotated file Show diff for this revision Revisions of this file
display_service.cpp Show diff for this revision Revisions of this file
lz.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
nRF51822.lib Show diff for this revision Revisions of this file
--- a/BLE_API.lib	Fri Jul 18 09:22:36 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#8890715aaf55
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Puck.lib	Tue Jul 29 14:03:29 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Nordic-Pucks/code/Puck/#ba0527c6b6d0
--- a/display_service.cpp	Fri Jul 18 09:22:36 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-#include "BLEDevice.h"
-
-uint8_t uuid_array_service[16]   = {'b', 'f', 't', 'j', ' ', 'd', 'i', 's', 'p', 'l', 'a', 'y', ' ', ' ', ' ', ' '};
-uint8_t uuid_array_command[16]    = {'b', 'f', 't', 'j', ' ', 'd', 'i', 's', 'p', 'l', 'a', 'y', ' ', 'c', 'o', 'm'};
-uint8_t uuid_array_data[16]    = {'b', 'f', 't', 'j', ' ', 'd', 'i', 's', 'p', 'l', 'a', 'y', ' ', 'd', 'a', 't'};
-
-const UUID uuid_service = UUID(uuid_array_service);
-const UUID uuid_command = UUID(uuid_array_command);
-const UUID uuid_data = UUID(uuid_array_data);
-
-uint8_t command_data[1];
-uint16_t command_data_length = 1;
-uint8_t data_data[20];
-uint16_t data_data_length = 20;
-
-GattCharacteristic command = GattCharacteristic(uuid_command, command_data, sizeof(command_data), sizeof(command_data), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
-GattCharacteristic data = GattCharacteristic(uuid_data, data_data, sizeof(data_data), sizeof(data_data), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
-
-GattCharacteristic *characteristics[] = {&command, &data};
-GattService display_service = GattService(uuid_service, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
\ No newline at end of file
--- a/lz.lib	Fri Jul 18 09:22:36 2014 +0000
+++ b/lz.lib	Tue Jul 29 14:03:29 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/Nordic-Pucks/code/lz/#ce4be867658b
+http://mbed.org/teams/Nordic-Pucks/code/lz/#0c9aeae76ab2
--- a/main.cpp	Fri Jul 18 09:22:36 2014 +0000
+++ b/main.cpp	Tue Jul 29 14:03:29 2014 +0000
@@ -1,14 +1,22 @@
 #include <mbed.h>
-#include <EPD.h>
-#include "mbed.h"
-#include "BLEDevice.h"
+#include "EPD.h"
 #include "lz.h"
 
-Serial py(USBTX, USBRX);
-BLEDevice ble;
-DigitalOut myled(LED1);
+
+#define LOG_LEVEL_VERBOSE
+#include "Puck.h"
+
+int receiveIndex = 0;
+
+Puck* puck = &Puck::getPuck();
 
-int receive_index = 0;
+
+EPD_Class EPD(p0, p2, p3, p8, p5, p6, p7);
+
+
+const UUID DISPLAY_SERVICE_UUID = UUID(stringToUUID("bftj display    "));
+const UUID COMMAND_UUID = UUID(stringToUUID("bftj display com"));
+const UUID DATA_UUID = UUID(stringToUUID("bftj display dat"));
 
 
  /*
@@ -47,183 +55,102 @@
 #define COMMAND_BEGIN_UPPER 4
 #define COMMAND_BEGIN_LOWER 5
 
-//#define IMAGE_SIZE 5808
-//#define Y_SIZE 176
-//#define X_SIZE 264
 #define IMAGE_SIZE 2904
+#define BUFFER_SIZE 2917
 #define Y_SIZE 88
 #define X_SIZE 264
-#define RECEIVE_BUFFER_SIZE 1000
-uint8_t image[IMAGE_SIZE];
-uint8_t receive_buffer[RECEIVE_BUFFER_SIZE];
+uint8_t buffer[BUFFER_SIZE];
+
+int currentCommand = COMMAND_NOOP;
+
+
+void reverseBufferSegment(int from, int to) {
+    for(int i = from; i < (to + from + 1) / 2; i++) {
+        int i2 = to + from - i - 1;
+        int temp = buffer[i];
+        buffer[i] = buffer[i2];
+        buffer[i2] = temp;
+    }
+    LOG_DEBUG("Reversed buffer from index %i to index %i.\n", from, to);
+}
+
 
-extern GattService display_service;
-extern GattCharacteristic command, data;
-int current_command = COMMAND_NOOP;
- 
-bool isConnected = false;
-bool isAdvertising = false;
- 
-const static uint8_t beaconPayload[] = {
-    0x00, 0x4C, // Company identifier code (0x004C == Apple)
-    0x02,       // ID
-    0x15,       // length of the remaining payload
-    0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, // UUID
-    0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61,
-    0x13, 0x37, // the major value to differenciate a location
-    0xFA, 0xCC, // the minor value to differenciate a location
-    0xC0        // 2's complement of the Tx power (-56dB) (now modified)
-};
-
-void onDataWritten(uint16_t handle)
-{
-    for (int i = 0; i < display_service.getCharacteristicCount(); i++) {
-        GattCharacteristic* characteristic = display_service.getCharacteristic(i);
-        characteristic->getMaxLength();
-        if (characteristic->getHandle() == handle) {
-            uint16_t max_length = characteristic->getMaxLength();
-            ble.readCharacteristicValue(handle, characteristic->getValuePtr(), &max_length);
+void onCommandWritten(uint8_t* value) {
+    currentCommand = value[0];
+    LOG_DEBUG("Received command: %i.\n", currentCommand);
+    
+    switch(currentCommand) {
+        
+        case COMMAND_BEGIN_UPPER:
+        case COMMAND_BEGIN_LOWER:
+            receiveIndex = BUFFER_SIZE;
+            break;
+        
+        case COMMAND_CLEAR:
+            LOG_INFO("Clearing display.\n");
+            EPD.begin(EPD_2_7);
+            EPD.start();
+            EPD.clear();
+            EPD.end();
             break;
-        }
+    
+        case COMMAND_IMAGE_UPPER:
+            LOG_INFO("Writing image to top half of display.\n");
+            reverseBufferSegment(receiveIndex, BUFFER_SIZE);
+            LOG_DEBUG("LZ_Uncompress(in: 0x%x, out 0x%x, insize: %i)\n", buffer + receiveIndex, buffer, BUFFER_SIZE - receiveIndex);
+            LZ_Uncompress(buffer + receiveIndex, buffer, BUFFER_SIZE - receiveIndex);
+            LOG_INFO("Uncompressed %i bytes of data.\n", BUFFER_SIZE - receiveIndex);
+            EPD.begin(EPD_2_7);
+            EPD.start();
+            EPD.image(buffer, 0, EPD.lines_per_display / 2);
+            EPD.end();
+            break;
+        
+        case COMMAND_IMAGE_LOWER:
+            LOG_INFO("Writing image to bottom half of display.\n");
+            reverseBufferSegment(receiveIndex, BUFFER_SIZE);
+            LZ_Uncompress(buffer + receiveIndex, buffer, BUFFER_SIZE - receiveIndex);
+            LOG_INFO("Uncompressed %i bytes of data.\n", BUFFER_SIZE - receiveIndex);
+            EPD.begin(EPD_2_7);
+            EPD.start();
+            EPD.image(buffer, EPD.lines_per_display / 2, EPD.lines_per_display);
+            EPD.end();
+            break;
+        
     }
     
-    if (command.getHandle() == handle) {
-        current_command = command.getValuePtr()[0];
-        
-        
-        py.printf("cmd: %i\n", current_command);
-        
-        if(current_command == COMMAND_BEGIN_UPPER || current_command == COMMAND_BEGIN_LOWER) {
-            receive_index = 0;
-        }
-    }
-    
-    if (data.getHandle() == handle) {
-        uint8_t* value = data.getValuePtr();
-        for(int i = 0; i < 20 && receive_index < IMAGE_SIZE; i++) {
-            receive_buffer[receive_index++] = value[i];
-        }
-        if (receive_index == IMAGE_SIZE) {
-            receive_index = 0;
-        }
+    currentCommand = COMMAND_NOOP;
+}
+
+void onDataWritten(uint8_t* value) {
+    LOG_VERBOSE("Data written, receiveIndex: %i\n", receiveIndex);
+    for(int i = 0; i < 20 && receiveIndex > 0; i++) {
+        buffer[--receiveIndex] = value[i];
     }
 }
 
-void disconnectionCallback(void)
-{
-    py.printf("Disconnected!\n");
-    isConnected = false;
-}
-
- void connectionCallback(void)
-{
-    py.printf("Connected!\n");
-    isConnected = true;
-    isAdvertising = false;
-}
-
-void uncompress_image() {
-    LZ_Uncompress(receive_buffer, image, receive_index);
-}
- 
-//uint8_t image[5808];
-
-void clear(){
-    for(int i=0;i<IMAGE_SIZE;i++){
-        image[i] = 0;
-    } 
-}
-
-void set_pixel(int x, int y, int color) {
-    int byte_x = x / 8;
-    int byte_w = X_SIZE / 8;
-    int byte_offset = x % 8;
-    int byte = image[byte_x + byte_w * y];
-    if(color) {
-        byte |= 1 << byte_offset;
-    } else {
-        byte &= ~(1 << byte_offset);     
-    }
-    image[byte_x + byte_w * y] = byte;
-}
 
 int main() {
+    LOG_INFO("Starting puck.\n");
+    
     DigitalOut SD_CS(p4);
     DigitalOut WORD_STOCK_CS(p26);
       
     SD_CS = 1;
     WORD_STOCK_CS = 1;
     
-    clear();
-    
-    EPD_Class EPD(p0, p2, p3, p8, p5, p6, p7);
+    puck->addCharacteristic(DISPLAY_SERVICE_UUID, COMMAND_UUID, 1);
+    puck->addCharacteristic(DISPLAY_SERVICE_UUID, DATA_UUID, 20);
     
-    EPD.begin(EPD_2_7);
-    EPD.start();
-    EPD.clear();
-    EPD.end();
     
-    ble.init();
-    ble.onDisconnection(disconnectionCallback);
-    ble.onConnection(connectionCallback);
-    ble.onDataWritten(onDataWritten);
+    puck->onCharacteristicWrite(&COMMAND_UUID, onCommandWritten);
+    puck->onCharacteristicWrite(&DATA_UUID, onDataWritten);
     
-
-    ble.addService(display_service);
+    puck->init(0x5EED);
     
-    myled = 1;
+    puck->countFreeMemory();
     
-    py.printf("Starting up.\n");
-    
-    current_command = COMMAND_NOOP;    
+    currentCommand = COMMAND_NOOP;    
 
-    while (true) {
-        ble.waitForEvent();
-        myled = !myled;
-        
-        if(current_command == COMMAND_CLEAR) {
-                
-                py.printf("Clearing.\n");
-                EPD.begin(EPD_2_7);
-                EPD.start();
-                EPD.clear();
-                EPD.end();
-                current_command = COMMAND_NOOP;
-        }
-        
-        
-        if(current_command == COMMAND_IMAGE_UPPER) {
-                py.printf("Uppering.\n");
-                uncompress_image();
-                EPD.begin(EPD_2_7);
-                EPD.start();
-                EPD.image(image, 0, EPD.lines_per_display / 2);
-                EPD.end();
-                current_command = COMMAND_NOOP;
-        }
-        
-        
-        if(current_command == COMMAND_IMAGE_LOWER) {
-                py.printf("Lowering.\n");
-                uncompress_image();
-                EPD.begin(EPD_2_7);
-                EPD.start();
-                EPD.image(image, EPD.lines_per_display / 2, EPD.lines_per_display);
-                EPD.end();
-                current_command = COMMAND_NOOP;
-        }
-        
-        
-        if(!isConnected && !isAdvertising) {
-            ble.clearAdvertisingPayload();
-            ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
-            ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
-            ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
-            ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA,
-                                             beaconPayload, sizeof(beaconPayload));
-            ble.startAdvertising();
-            py.printf("Restarting the advertising process\n");
-            isAdvertising = true;
-       }     
-    }   
+    while (puck->drive());   
 }
\ No newline at end of file
--- a/nRF51822.lib	Fri Jul 18 09:22:36 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#bd0186ce644a