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
main.cpp
- Committer:
- sigveseb
- Date:
- 2014-07-18
- Revision:
- 1:42882ba4c901
- Parent:
- 0:7499fa0a8ecb
- Child:
- 3:4ff226c4fe2a
File content as of revision 1:42882ba4c901:
#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 #define RECEIVE_BUFFER_SIZE 1000 uint8_t image[IMAGE_SIZE]; uint8_t receive_buffer[RECEIVE_BUFFER_SIZE]; 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); 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; } } } 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() { 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.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"); 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; } } }