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
Diff: main.cpp
- Revision:
- 0:7499fa0a8ecb
- Child:
- 1:42882ba4c901
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Jul 17 14:16:16 2014 +0000 @@ -0,0 +1,218 @@ +#include <mbed.h> +#include <EPD.h> +#include "mbed.h" +#include "BLEDevice.h" +#include "lz.h" + +Serial py(USBTX, USBRX); +BLEDevice ble; +DigitalOut myled(LED1); + +int receive_index = 0; + + + /* + + connections: + + +LPC1768 <--> nRF51822 <--> Shield +---------||------------||-------- + p12 <--> p2 <--> D2 (M_EPD_PANEL_ON) + p13 <--> p3 <--> D3 (M_EPD_BORDER) + p14 <--> p4 <--> D4 (M_/SD_CS) + p25 <--> p5 <--> D5 (M_EPD_PWM) + p16 <--> p6 <--> D6 (M_EPD_/RESET) + p17 <--> p7 <--> D7 (M_EPD_BUSY) + p18 <--> p8 <--> D8 (M_EPD_DISCHARGE) + p19 <--> p26 <--> D9 (M_/WORD_STOCK_CS) + p20 <--> p0 <--> D10 (M_/EPD_CS) + p21 <--> p27 <--> A1 (M_OE123) + p22 <--> p28 <--> A2 (M_CKV) + p23 <--> p29 <--> A3 (M_STV_IN) + + p5 <--> p20 <--> MOSI + p6 <--> p22 <--> MISO + p7 <--> p25 <--> SCK + + VCC <--> VCC + GND <--> GND + + */ + +#define COMMAND_NOOP 0 +#define COMMAND_CLEAR 1 +#define COMMAND_IMAGE_UPPER 2 +#define COMMAND_IMAGE_LOWER 3 +#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 Y_SIZE 88 +#define X_SIZE 264 + +uint8_t image[IMAGE_SIZE]; + +extern GattService display_service; +extern GattCharacteristic command, data; +int current_command = COMMAND_NOOP; + +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); + break; + } + } + + if (command.getHandle() == handle) { + current_command = command.getValuePtr()[0]; + + + py.printf("%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++) { + image[receive_index++] = value[i]; + } + if (receive_index == IMAGE_SIZE) { + receive_index = 0; + if(current_command == COMMAND_BEGIN_UPPER) { current_command = COMMAND_IMAGE_UPPER; } + if(current_command == COMMAND_BEGIN_LOWER) { current_command = COMMAND_IMAGE_LOWER; } + } + } +} + +void disconnectionCallback(void) +{ + py.printf("Disconnected!\n"); + py.printf("Restarting the advertising process\n"); + ble.startAdvertising(); +} + + void connectionCallback(void) +{ + py.printf("Connected!\n"); +} + + + +//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() { + 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); + + EPD.begin(EPD_2_7); + EPD.start(); + EPD.clear(); + EPD.end(); + + ble.init(); + ble.onDisconnection(disconnectionCallback); + ble.onConnection(connectionCallback); + ble.onDataWritten(onDataWritten); + 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(); + + ble.addService(display_service); + + myled = 1; + + py.printf("Starting up.\n"); + + current_command = 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"); + 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"); + EPD.begin(EPD_2_7); + EPD.start(); + EPD.image(image, EPD.lines_per_display / 2); + EPD.end(); + current_command = COMMAND_NOOP; + } + + } +} \ No newline at end of file