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@3:4ff226c4fe2a, 2014-07-29 (annotated)
- Committer:
- sigveseb
- Date:
- Tue Jul 29 14:03:29 2014 +0000
- Revision:
- 3:4ff226c4fe2a
- Parent:
- 1:42882ba4c901
- Child:
- 5:5491fb58107e
Update display puck to use new puck lib
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sigveseb | 0:7499fa0a8ecb | 1 | #include <mbed.h> |
sigveseb | 3:4ff226c4fe2a | 2 | #include "EPD.h" |
sigveseb | 0:7499fa0a8ecb | 3 | #include "lz.h" |
sigveseb | 0:7499fa0a8ecb | 4 | |
sigveseb | 3:4ff226c4fe2a | 5 | |
sigveseb | 3:4ff226c4fe2a | 6 | #define LOG_LEVEL_VERBOSE |
sigveseb | 3:4ff226c4fe2a | 7 | #include "Puck.h" |
sigveseb | 3:4ff226c4fe2a | 8 | |
sigveseb | 3:4ff226c4fe2a | 9 | int receiveIndex = 0; |
sigveseb | 3:4ff226c4fe2a | 10 | |
sigveseb | 3:4ff226c4fe2a | 11 | Puck* puck = &Puck::getPuck(); |
sigveseb | 0:7499fa0a8ecb | 12 | |
sigveseb | 3:4ff226c4fe2a | 13 | |
sigveseb | 3:4ff226c4fe2a | 14 | EPD_Class EPD(p0, p2, p3, p8, p5, p6, p7); |
sigveseb | 3:4ff226c4fe2a | 15 | |
sigveseb | 3:4ff226c4fe2a | 16 | |
sigveseb | 3:4ff226c4fe2a | 17 | const UUID DISPLAY_SERVICE_UUID = UUID(stringToUUID("bftj display ")); |
sigveseb | 3:4ff226c4fe2a | 18 | const UUID COMMAND_UUID = UUID(stringToUUID("bftj display com")); |
sigveseb | 3:4ff226c4fe2a | 19 | const UUID DATA_UUID = UUID(stringToUUID("bftj display dat")); |
sigveseb | 0:7499fa0a8ecb | 20 | |
sigveseb | 0:7499fa0a8ecb | 21 | |
sigveseb | 0:7499fa0a8ecb | 22 | /* |
sigveseb | 0:7499fa0a8ecb | 23 | |
sigveseb | 0:7499fa0a8ecb | 24 | connections: |
sigveseb | 0:7499fa0a8ecb | 25 | |
sigveseb | 0:7499fa0a8ecb | 26 | |
sigveseb | 0:7499fa0a8ecb | 27 | LPC1768 <--> nRF51822 <--> Shield |
sigveseb | 0:7499fa0a8ecb | 28 | ---------||------------||-------- |
sigveseb | 0:7499fa0a8ecb | 29 | p12 <--> p2 <--> D2 (M_EPD_PANEL_ON) |
sigveseb | 0:7499fa0a8ecb | 30 | p13 <--> p3 <--> D3 (M_EPD_BORDER) |
sigveseb | 0:7499fa0a8ecb | 31 | p14 <--> p4 <--> D4 (M_/SD_CS) |
sigveseb | 0:7499fa0a8ecb | 32 | p25 <--> p5 <--> D5 (M_EPD_PWM) |
sigveseb | 0:7499fa0a8ecb | 33 | p16 <--> p6 <--> D6 (M_EPD_/RESET) |
sigveseb | 0:7499fa0a8ecb | 34 | p17 <--> p7 <--> D7 (M_EPD_BUSY) |
sigveseb | 0:7499fa0a8ecb | 35 | p18 <--> p8 <--> D8 (M_EPD_DISCHARGE) |
sigveseb | 0:7499fa0a8ecb | 36 | p19 <--> p26 <--> D9 (M_/WORD_STOCK_CS) |
sigveseb | 0:7499fa0a8ecb | 37 | p20 <--> p0 <--> D10 (M_/EPD_CS) |
sigveseb | 0:7499fa0a8ecb | 38 | p21 <--> p27 <--> A1 (M_OE123) |
sigveseb | 0:7499fa0a8ecb | 39 | p22 <--> p28 <--> A2 (M_CKV) |
sigveseb | 0:7499fa0a8ecb | 40 | p23 <--> p29 <--> A3 (M_STV_IN) |
sigveseb | 0:7499fa0a8ecb | 41 | |
sigveseb | 0:7499fa0a8ecb | 42 | p5 <--> p20 <--> MOSI |
sigveseb | 0:7499fa0a8ecb | 43 | p6 <--> p22 <--> MISO |
sigveseb | 0:7499fa0a8ecb | 44 | p7 <--> p25 <--> SCK |
sigveseb | 0:7499fa0a8ecb | 45 | |
sigveseb | 0:7499fa0a8ecb | 46 | VCC <--> VCC |
sigveseb | 0:7499fa0a8ecb | 47 | GND <--> GND |
sigveseb | 0:7499fa0a8ecb | 48 | |
sigveseb | 0:7499fa0a8ecb | 49 | */ |
sigveseb | 0:7499fa0a8ecb | 50 | |
sigveseb | 0:7499fa0a8ecb | 51 | #define COMMAND_NOOP 0 |
sigveseb | 0:7499fa0a8ecb | 52 | #define COMMAND_CLEAR 1 |
sigveseb | 0:7499fa0a8ecb | 53 | #define COMMAND_IMAGE_UPPER 2 |
sigveseb | 0:7499fa0a8ecb | 54 | #define COMMAND_IMAGE_LOWER 3 |
sigveseb | 0:7499fa0a8ecb | 55 | #define COMMAND_BEGIN_UPPER 4 |
sigveseb | 0:7499fa0a8ecb | 56 | #define COMMAND_BEGIN_LOWER 5 |
sigveseb | 0:7499fa0a8ecb | 57 | |
sigveseb | 0:7499fa0a8ecb | 58 | #define IMAGE_SIZE 2904 |
sigveseb | 3:4ff226c4fe2a | 59 | #define BUFFER_SIZE 2917 |
sigveseb | 0:7499fa0a8ecb | 60 | #define Y_SIZE 88 |
sigveseb | 0:7499fa0a8ecb | 61 | #define X_SIZE 264 |
sigveseb | 3:4ff226c4fe2a | 62 | uint8_t buffer[BUFFER_SIZE]; |
sigveseb | 3:4ff226c4fe2a | 63 | |
sigveseb | 3:4ff226c4fe2a | 64 | int currentCommand = COMMAND_NOOP; |
sigveseb | 3:4ff226c4fe2a | 65 | |
sigveseb | 3:4ff226c4fe2a | 66 | |
sigveseb | 3:4ff226c4fe2a | 67 | void reverseBufferSegment(int from, int to) { |
sigveseb | 3:4ff226c4fe2a | 68 | for(int i = from; i < (to + from + 1) / 2; i++) { |
sigveseb | 3:4ff226c4fe2a | 69 | int i2 = to + from - i - 1; |
sigveseb | 3:4ff226c4fe2a | 70 | int temp = buffer[i]; |
sigveseb | 3:4ff226c4fe2a | 71 | buffer[i] = buffer[i2]; |
sigveseb | 3:4ff226c4fe2a | 72 | buffer[i2] = temp; |
sigveseb | 3:4ff226c4fe2a | 73 | } |
sigveseb | 3:4ff226c4fe2a | 74 | LOG_DEBUG("Reversed buffer from index %i to index %i.\n", from, to); |
sigveseb | 3:4ff226c4fe2a | 75 | } |
sigveseb | 3:4ff226c4fe2a | 76 | |
sigveseb | 0:7499fa0a8ecb | 77 | |
sigveseb | 3:4ff226c4fe2a | 78 | void onCommandWritten(uint8_t* value) { |
sigveseb | 3:4ff226c4fe2a | 79 | currentCommand = value[0]; |
sigveseb | 3:4ff226c4fe2a | 80 | LOG_DEBUG("Received command: %i.\n", currentCommand); |
sigveseb | 3:4ff226c4fe2a | 81 | |
sigveseb | 3:4ff226c4fe2a | 82 | switch(currentCommand) { |
sigveseb | 3:4ff226c4fe2a | 83 | |
sigveseb | 3:4ff226c4fe2a | 84 | case COMMAND_BEGIN_UPPER: |
sigveseb | 3:4ff226c4fe2a | 85 | case COMMAND_BEGIN_LOWER: |
sigveseb | 3:4ff226c4fe2a | 86 | receiveIndex = BUFFER_SIZE; |
sigveseb | 3:4ff226c4fe2a | 87 | break; |
sigveseb | 3:4ff226c4fe2a | 88 | |
sigveseb | 3:4ff226c4fe2a | 89 | case COMMAND_CLEAR: |
sigveseb | 3:4ff226c4fe2a | 90 | LOG_INFO("Clearing display.\n"); |
sigveseb | 3:4ff226c4fe2a | 91 | EPD.begin(EPD_2_7); |
sigveseb | 3:4ff226c4fe2a | 92 | EPD.start(); |
sigveseb | 3:4ff226c4fe2a | 93 | EPD.clear(); |
sigveseb | 3:4ff226c4fe2a | 94 | EPD.end(); |
sigveseb | 0:7499fa0a8ecb | 95 | break; |
sigveseb | 3:4ff226c4fe2a | 96 | |
sigveseb | 3:4ff226c4fe2a | 97 | case COMMAND_IMAGE_UPPER: |
sigveseb | 3:4ff226c4fe2a | 98 | LOG_INFO("Writing image to top half of display.\n"); |
sigveseb | 3:4ff226c4fe2a | 99 | reverseBufferSegment(receiveIndex, BUFFER_SIZE); |
sigveseb | 3:4ff226c4fe2a | 100 | LOG_DEBUG("LZ_Uncompress(in: 0x%x, out 0x%x, insize: %i)\n", buffer + receiveIndex, buffer, BUFFER_SIZE - receiveIndex); |
sigveseb | 3:4ff226c4fe2a | 101 | LZ_Uncompress(buffer + receiveIndex, buffer, BUFFER_SIZE - receiveIndex); |
sigveseb | 3:4ff226c4fe2a | 102 | LOG_INFO("Uncompressed %i bytes of data.\n", BUFFER_SIZE - receiveIndex); |
sigveseb | 3:4ff226c4fe2a | 103 | EPD.begin(EPD_2_7); |
sigveseb | 3:4ff226c4fe2a | 104 | EPD.start(); |
sigveseb | 3:4ff226c4fe2a | 105 | EPD.image(buffer, 0, EPD.lines_per_display / 2); |
sigveseb | 3:4ff226c4fe2a | 106 | EPD.end(); |
sigveseb | 3:4ff226c4fe2a | 107 | break; |
sigveseb | 3:4ff226c4fe2a | 108 | |
sigveseb | 3:4ff226c4fe2a | 109 | case COMMAND_IMAGE_LOWER: |
sigveseb | 3:4ff226c4fe2a | 110 | LOG_INFO("Writing image to bottom half of display.\n"); |
sigveseb | 3:4ff226c4fe2a | 111 | reverseBufferSegment(receiveIndex, BUFFER_SIZE); |
sigveseb | 3:4ff226c4fe2a | 112 | LZ_Uncompress(buffer + receiveIndex, buffer, BUFFER_SIZE - receiveIndex); |
sigveseb | 3:4ff226c4fe2a | 113 | LOG_INFO("Uncompressed %i bytes of data.\n", BUFFER_SIZE - receiveIndex); |
sigveseb | 3:4ff226c4fe2a | 114 | EPD.begin(EPD_2_7); |
sigveseb | 3:4ff226c4fe2a | 115 | EPD.start(); |
sigveseb | 3:4ff226c4fe2a | 116 | EPD.image(buffer, EPD.lines_per_display / 2, EPD.lines_per_display); |
sigveseb | 3:4ff226c4fe2a | 117 | EPD.end(); |
sigveseb | 3:4ff226c4fe2a | 118 | break; |
sigveseb | 3:4ff226c4fe2a | 119 | |
sigveseb | 0:7499fa0a8ecb | 120 | } |
sigveseb | 0:7499fa0a8ecb | 121 | |
sigveseb | 3:4ff226c4fe2a | 122 | currentCommand = COMMAND_NOOP; |
sigveseb | 3:4ff226c4fe2a | 123 | } |
sigveseb | 3:4ff226c4fe2a | 124 | |
sigveseb | 3:4ff226c4fe2a | 125 | void onDataWritten(uint8_t* value) { |
sigveseb | 3:4ff226c4fe2a | 126 | LOG_VERBOSE("Data written, receiveIndex: %i\n", receiveIndex); |
sigveseb | 3:4ff226c4fe2a | 127 | for(int i = 0; i < 20 && receiveIndex > 0; i++) { |
sigveseb | 3:4ff226c4fe2a | 128 | buffer[--receiveIndex] = value[i]; |
sigveseb | 0:7499fa0a8ecb | 129 | } |
sigveseb | 0:7499fa0a8ecb | 130 | } |
sigveseb | 0:7499fa0a8ecb | 131 | |
sigveseb | 0:7499fa0a8ecb | 132 | |
sigveseb | 0:7499fa0a8ecb | 133 | int main() { |
sigveseb | 3:4ff226c4fe2a | 134 | LOG_INFO("Starting puck.\n"); |
sigveseb | 3:4ff226c4fe2a | 135 | |
sigveseb | 0:7499fa0a8ecb | 136 | DigitalOut SD_CS(p4); |
sigveseb | 0:7499fa0a8ecb | 137 | DigitalOut WORD_STOCK_CS(p26); |
sigveseb | 0:7499fa0a8ecb | 138 | |
sigveseb | 0:7499fa0a8ecb | 139 | SD_CS = 1; |
sigveseb | 0:7499fa0a8ecb | 140 | WORD_STOCK_CS = 1; |
sigveseb | 0:7499fa0a8ecb | 141 | |
sigveseb | 3:4ff226c4fe2a | 142 | puck->addCharacteristic(DISPLAY_SERVICE_UUID, COMMAND_UUID, 1); |
sigveseb | 3:4ff226c4fe2a | 143 | puck->addCharacteristic(DISPLAY_SERVICE_UUID, DATA_UUID, 20); |
sigveseb | 0:7499fa0a8ecb | 144 | |
sigveseb | 0:7499fa0a8ecb | 145 | |
sigveseb | 3:4ff226c4fe2a | 146 | puck->onCharacteristicWrite(&COMMAND_UUID, onCommandWritten); |
sigveseb | 3:4ff226c4fe2a | 147 | puck->onCharacteristicWrite(&DATA_UUID, onDataWritten); |
sigveseb | 0:7499fa0a8ecb | 148 | |
sigveseb | 3:4ff226c4fe2a | 149 | puck->init(0x5EED); |
sigveseb | 0:7499fa0a8ecb | 150 | |
sigveseb | 3:4ff226c4fe2a | 151 | puck->countFreeMemory(); |
sigveseb | 0:7499fa0a8ecb | 152 | |
sigveseb | 3:4ff226c4fe2a | 153 | currentCommand = COMMAND_NOOP; |
sigveseb | 0:7499fa0a8ecb | 154 | |
sigveseb | 3:4ff226c4fe2a | 155 | while (puck->drive()); |
sigveseb | 0:7499fa0a8ecb | 156 | } |