Library for interacting with seeedstudio epaper

Dependents:   display-puck display-puck

Committer:
sigveseb
Date:
Thu Jul 17 14:15:53 2014 +0000
Revision:
0:6ac5ba1343bf
Child:
1:2f62e2b80305
-

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sigveseb 0:6ac5ba1343bf 1 // Copyright 2013 Pervasive Displays, Inc.
sigveseb 0:6ac5ba1343bf 2 //
sigveseb 0:6ac5ba1343bf 3 // Licensed under the Apache License, Version 2.0 (the "License");
sigveseb 0:6ac5ba1343bf 4 // you may not use this file except in compliance with the License.
sigveseb 0:6ac5ba1343bf 5 // You may obtain a copy of the License at:
sigveseb 0:6ac5ba1343bf 6 //
sigveseb 0:6ac5ba1343bf 7 // http://www.apache.org/licenses/LICENSE-2.0
sigveseb 0:6ac5ba1343bf 8 //
sigveseb 0:6ac5ba1343bf 9 // Unless required by applicable law or agreed to in writing,
sigveseb 0:6ac5ba1343bf 10 // software distributed under the License is distributed on an
sigveseb 0:6ac5ba1343bf 11 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
sigveseb 0:6ac5ba1343bf 12 // express or implied. See the License for the specific language
sigveseb 0:6ac5ba1343bf 13 // governing permissions and limitations under the License.
sigveseb 0:6ac5ba1343bf 14
sigveseb 0:6ac5ba1343bf 15
sigveseb 0:6ac5ba1343bf 16 #include <limits.h>
sigveseb 0:6ac5ba1343bf 17 #include <SPI.h>
sigveseb 0:6ac5ba1343bf 18
sigveseb 0:6ac5ba1343bf 19 #include "EPD.h"
sigveseb 0:6ac5ba1343bf 20 #include <mbed.h>
sigveseb 0:6ac5ba1343bf 21
sigveseb 0:6ac5ba1343bf 22 // delays - more consistent naming
sigveseb 0:6ac5ba1343bf 23 #define Delay_ms(ms) delay(ms)
sigveseb 0:6ac5ba1343bf 24 #define Delay_us(us) delayMicroseconds(us)
sigveseb 0:6ac5ba1343bf 25
sigveseb 0:6ac5ba1343bf 26 // inline arrays
sigveseb 0:6ac5ba1343bf 27 #define ARRAY(type, ...) ((type[]){__VA_ARGS__})
sigveseb 0:6ac5ba1343bf 28 #define CU8(...) (ARRAY(const uint8_t, __VA_ARGS__))
sigveseb 0:6ac5ba1343bf 29
sigveseb 0:6ac5ba1343bf 30 Timer timer;
sigveseb 0:6ac5ba1343bf 31 SPI spi(p20, p22, p25);
sigveseb 0:6ac5ba1343bf 32
sigveseb 0:6ac5ba1343bf 33
sigveseb 0:6ac5ba1343bf 34 Serial pq(USBTX, USBRX);
sigveseb 0:6ac5ba1343bf 35
sigveseb 0:6ac5ba1343bf 36 static void SPI_put(uint8_t c);
sigveseb 0:6ac5ba1343bf 37 static void SPI_put_wait(uint8_t c, DigitalIn busy_pin);
sigveseb 0:6ac5ba1343bf 38 static void SPI_send(DigitalOut cs_pin, const uint8_t *buffer, uint16_t length);
sigveseb 0:6ac5ba1343bf 39 static void SPI_on();
sigveseb 0:6ac5ba1343bf 40
sigveseb 0:6ac5ba1343bf 41
sigveseb 0:6ac5ba1343bf 42 EPD_Class::EPD_Class(PinName Pin_EPD_CS, PinName Pin_PANEL_ON, PinName Pin_BORDER, PinName Pin_DISCHARGE, PinName Pin_PWM, PinName Pin_RESET, PinName Pin_BUSY) :
sigveseb 0:6ac5ba1343bf 43 EPD_Pin_EPD_CS(Pin_EPD_CS),
sigveseb 0:6ac5ba1343bf 44 EPD_Pin_PANEL_ON(Pin_PANEL_ON),
sigveseb 0:6ac5ba1343bf 45 EPD_Pin_BORDER(Pin_BORDER),
sigveseb 0:6ac5ba1343bf 46 EPD_Pin_DISCHARGE(Pin_DISCHARGE),
sigveseb 0:6ac5ba1343bf 47 EPD_Pin_PWM(Pin_PWM),
sigveseb 0:6ac5ba1343bf 48 EPD_Pin_RESET(Pin_RESET),
sigveseb 0:6ac5ba1343bf 49 EPD_Pin_BUSY(Pin_BUSY) {
sigveseb 0:6ac5ba1343bf 50
sigveseb 0:6ac5ba1343bf 51 }
sigveseb 0:6ac5ba1343bf 52
sigveseb 0:6ac5ba1343bf 53 void EPD_Class::begin(EPD_size sz)
sigveseb 0:6ac5ba1343bf 54 {
sigveseb 0:6ac5ba1343bf 55 this->size = sz;
sigveseb 0:6ac5ba1343bf 56 this->stage_time = 480; // milliseconds
sigveseb 0:6ac5ba1343bf 57 this->lines_per_display = 96;
sigveseb 0:6ac5ba1343bf 58 this->dots_per_line = 128;
sigveseb 0:6ac5ba1343bf 59 this->bytes_per_line = 128 / 8;
sigveseb 0:6ac5ba1343bf 60 this->bytes_per_scan = 96 / 4;
sigveseb 0:6ac5ba1343bf 61 this->filler = false;
sigveseb 0:6ac5ba1343bf 62 timer.start();
sigveseb 0:6ac5ba1343bf 63 this->EPD_Pin_PWM.period(1.0/300000.0);
sigveseb 0:6ac5ba1343bf 64
sigveseb 0:6ac5ba1343bf 65
sigveseb 0:6ac5ba1343bf 66 // display size dependant items
sigveseb 0:6ac5ba1343bf 67 {
sigveseb 0:6ac5ba1343bf 68 static uint8_t cs[] = {0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00};
sigveseb 0:6ac5ba1343bf 69 static uint8_t gs[] = {0x72, 0x03};
sigveseb 0:6ac5ba1343bf 70 this->channel_select = cs;
sigveseb 0:6ac5ba1343bf 71 this->channel_select_length = sizeof(cs);
sigveseb 0:6ac5ba1343bf 72 this->gate_source = gs;
sigveseb 0:6ac5ba1343bf 73 this->gate_source_length = sizeof(gs);
sigveseb 0:6ac5ba1343bf 74 }
sigveseb 0:6ac5ba1343bf 75
sigveseb 0:6ac5ba1343bf 76 // set up size structure
sigveseb 0:6ac5ba1343bf 77 switch (size) {
sigveseb 0:6ac5ba1343bf 78 default:
sigveseb 0:6ac5ba1343bf 79 case EPD_1_44: // default so no change
sigveseb 0:6ac5ba1343bf 80 break;
sigveseb 0:6ac5ba1343bf 81
sigveseb 0:6ac5ba1343bf 82 case EPD_2_0: {
sigveseb 0:6ac5ba1343bf 83 this->lines_per_display = 96;
sigveseb 0:6ac5ba1343bf 84 this->dots_per_line = 200;
sigveseb 0:6ac5ba1343bf 85 this->bytes_per_line = 200 / 8;
sigveseb 0:6ac5ba1343bf 86 this->bytes_per_scan = 96 / 4;
sigveseb 0:6ac5ba1343bf 87 this->filler = true;
sigveseb 0:6ac5ba1343bf 88 static uint8_t cs[] = {0x72, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xe0, 0x00};
sigveseb 0:6ac5ba1343bf 89 static uint8_t gs[] = {0x72, 0x03};
sigveseb 0:6ac5ba1343bf 90 this->channel_select = cs;
sigveseb 0:6ac5ba1343bf 91 this->channel_select_length = sizeof(cs);
sigveseb 0:6ac5ba1343bf 92 this->gate_source = gs;
sigveseb 0:6ac5ba1343bf 93 this->gate_source_length = sizeof(gs);
sigveseb 0:6ac5ba1343bf 94 break;
sigveseb 0:6ac5ba1343bf 95 }
sigveseb 0:6ac5ba1343bf 96
sigveseb 0:6ac5ba1343bf 97 case EPD_2_7: {
sigveseb 0:6ac5ba1343bf 98 this->stage_time = 630; // milliseconds
sigveseb 0:6ac5ba1343bf 99 this->lines_per_display = 176;
sigveseb 0:6ac5ba1343bf 100 this->dots_per_line = 264;
sigveseb 0:6ac5ba1343bf 101 this->bytes_per_line = 264 / 8;
sigveseb 0:6ac5ba1343bf 102 this->bytes_per_scan = 176 / 4;
sigveseb 0:6ac5ba1343bf 103 this->filler = true;
sigveseb 0:6ac5ba1343bf 104 static uint8_t cs[] = {0x72, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x00};
sigveseb 0:6ac5ba1343bf 105 static uint8_t gs[] = {0x72, 0x00};
sigveseb 0:6ac5ba1343bf 106 this->channel_select = cs;
sigveseb 0:6ac5ba1343bf 107 this->channel_select_length = sizeof(cs);
sigveseb 0:6ac5ba1343bf 108 this->gate_source = gs;
sigveseb 0:6ac5ba1343bf 109 this->gate_source_length = sizeof(gs);
sigveseb 0:6ac5ba1343bf 110 break;
sigveseb 0:6ac5ba1343bf 111 }
sigveseb 0:6ac5ba1343bf 112 }
sigveseb 0:6ac5ba1343bf 113
sigveseb 0:6ac5ba1343bf 114 this->factored_stage_time = this->stage_time;
sigveseb 0:6ac5ba1343bf 115 }
sigveseb 0:6ac5ba1343bf 116
sigveseb 0:6ac5ba1343bf 117
sigveseb 0:6ac5ba1343bf 118 void EPD_Class::start() {
sigveseb 0:6ac5ba1343bf 119
sigveseb 0:6ac5ba1343bf 120 this->EPD_Pin_PWM = 0.5;
sigveseb 0:6ac5ba1343bf 121 this->EPD_Pin_RESET = 0;
sigveseb 0:6ac5ba1343bf 122 this->EPD_Pin_PANEL_ON = 0;
sigveseb 0:6ac5ba1343bf 123 this->EPD_Pin_DISCHARGE = 0;
sigveseb 0:6ac5ba1343bf 124 this->EPD_Pin_BORDER = 0;
sigveseb 0:6ac5ba1343bf 125 this->EPD_Pin_EPD_CS = 0;
sigveseb 0:6ac5ba1343bf 126
sigveseb 0:6ac5ba1343bf 127
sigveseb 0:6ac5ba1343bf 128 spi.format(8,0);
sigveseb 0:6ac5ba1343bf 129 spi.frequency(10000000);
sigveseb 0:6ac5ba1343bf 130 SPI_on();
sigveseb 0:6ac5ba1343bf 131
sigveseb 0:6ac5ba1343bf 132 wait_ms(5);
sigveseb 0:6ac5ba1343bf 133 this->EPD_Pin_PANEL_ON = 1;
sigveseb 0:6ac5ba1343bf 134 wait_ms(10);
sigveseb 0:6ac5ba1343bf 135
sigveseb 0:6ac5ba1343bf 136 this->EPD_Pin_RESET = 1;
sigveseb 0:6ac5ba1343bf 137 this->EPD_Pin_BORDER = 1;
sigveseb 0:6ac5ba1343bf 138 this->EPD_Pin_EPD_CS = 1;
sigveseb 0:6ac5ba1343bf 139 wait_ms(5);
sigveseb 0:6ac5ba1343bf 140
sigveseb 0:6ac5ba1343bf 141 this->EPD_Pin_RESET = 0;
sigveseb 0:6ac5ba1343bf 142 wait_ms(5);
sigveseb 0:6ac5ba1343bf 143
sigveseb 0:6ac5ba1343bf 144 this->EPD_Pin_RESET = 1;
sigveseb 0:6ac5ba1343bf 145 wait_ms(5);
sigveseb 0:6ac5ba1343bf 146
sigveseb 0:6ac5ba1343bf 147 // wait for COG to become ready
sigveseb 0:6ac5ba1343bf 148
sigveseb 0:6ac5ba1343bf 149
sigveseb 0:6ac5ba1343bf 150 pq.printf("waiting...");
sigveseb 0:6ac5ba1343bf 151 while (this->EPD_Pin_BUSY) {
sigveseb 0:6ac5ba1343bf 152 }
sigveseb 0:6ac5ba1343bf 153
sigveseb 0:6ac5ba1343bf 154 pq.printf(" OK!\n");
sigveseb 0:6ac5ba1343bf 155
sigveseb 0:6ac5ba1343bf 156 // channel select
sigveseb 0:6ac5ba1343bf 157 wait_us(10);
sigveseb 0:6ac5ba1343bf 158 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x01), 2);
sigveseb 0:6ac5ba1343bf 159 wait_us(10);
sigveseb 0:6ac5ba1343bf 160 SPI_send(this->EPD_Pin_EPD_CS, this->channel_select, this->channel_select_length);
sigveseb 0:6ac5ba1343bf 161
sigveseb 0:6ac5ba1343bf 162 // DC/DC frequency
sigveseb 0:6ac5ba1343bf 163 wait_us(10);
sigveseb 0:6ac5ba1343bf 164 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x06), 2);
sigveseb 0:6ac5ba1343bf 165 wait_us(10);
sigveseb 0:6ac5ba1343bf 166 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0xff), 2);
sigveseb 0:6ac5ba1343bf 167
sigveseb 0:6ac5ba1343bf 168 // high power mode osc
sigveseb 0:6ac5ba1343bf 169 wait_us(10);
sigveseb 0:6ac5ba1343bf 170 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x07), 2);
sigveseb 0:6ac5ba1343bf 171 wait_us(10);
sigveseb 0:6ac5ba1343bf 172 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x9d), 2);
sigveseb 0:6ac5ba1343bf 173
sigveseb 0:6ac5ba1343bf 174
sigveseb 0:6ac5ba1343bf 175 // disable ADC
sigveseb 0:6ac5ba1343bf 176 wait_us(10);
sigveseb 0:6ac5ba1343bf 177 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x08), 2);
sigveseb 0:6ac5ba1343bf 178 wait_us(10);
sigveseb 0:6ac5ba1343bf 179 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x00), 2);
sigveseb 0:6ac5ba1343bf 180
sigveseb 0:6ac5ba1343bf 181 // Vcom level
sigveseb 0:6ac5ba1343bf 182 wait_us(10);
sigveseb 0:6ac5ba1343bf 183 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x09), 2);
sigveseb 0:6ac5ba1343bf 184 wait_us(10);
sigveseb 0:6ac5ba1343bf 185 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0xd0, 0x00), 3);
sigveseb 0:6ac5ba1343bf 186
sigveseb 0:6ac5ba1343bf 187 // gate and source voltage levels
sigveseb 0:6ac5ba1343bf 188 wait_us(10);
sigveseb 0:6ac5ba1343bf 189 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
sigveseb 0:6ac5ba1343bf 190 wait_us(10);
sigveseb 0:6ac5ba1343bf 191 SPI_send(this->EPD_Pin_EPD_CS, this->gate_source, this->gate_source_length);
sigveseb 0:6ac5ba1343bf 192
sigveseb 0:6ac5ba1343bf 193
sigveseb 0:6ac5ba1343bf 194 this->EPD_Pin_PWM = 0.5;
sigveseb 0:6ac5ba1343bf 195 wait_ms(5); // pwm toggle >= 5ms
sigveseb 0:6ac5ba1343bf 196
sigveseb 0:6ac5ba1343bf 197 // driver latch on
sigveseb 0:6ac5ba1343bf 198 wait_us(10);
sigveseb 0:6ac5ba1343bf 199 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x03), 2);
sigveseb 0:6ac5ba1343bf 200 wait_us(10);
sigveseb 0:6ac5ba1343bf 201 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x01), 2);
sigveseb 0:6ac5ba1343bf 202
sigveseb 0:6ac5ba1343bf 203 // driver latch off
sigveseb 0:6ac5ba1343bf 204 wait_us(10);
sigveseb 0:6ac5ba1343bf 205 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x03), 2);
sigveseb 0:6ac5ba1343bf 206 wait_us(10);
sigveseb 0:6ac5ba1343bf 207 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x00), 2);
sigveseb 0:6ac5ba1343bf 208
sigveseb 0:6ac5ba1343bf 209 wait_ms(5);
sigveseb 0:6ac5ba1343bf 210
sigveseb 0:6ac5ba1343bf 211 // charge pump positive voltage on
sigveseb 0:6ac5ba1343bf 212 wait_us(10);
sigveseb 0:6ac5ba1343bf 213 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
sigveseb 0:6ac5ba1343bf 214 wait_us(10);
sigveseb 0:6ac5ba1343bf 215 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x01), 2);
sigveseb 0:6ac5ba1343bf 216
sigveseb 0:6ac5ba1343bf 217 // final delay before PWM off
sigveseb 0:6ac5ba1343bf 218 wait_ms(30);
sigveseb 0:6ac5ba1343bf 219 this->EPD_Pin_PWM = 0;
sigveseb 0:6ac5ba1343bf 220
sigveseb 0:6ac5ba1343bf 221 // charge pump negative voltage on
sigveseb 0:6ac5ba1343bf 222 wait_us(10);
sigveseb 0:6ac5ba1343bf 223 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
sigveseb 0:6ac5ba1343bf 224 wait_us(10);
sigveseb 0:6ac5ba1343bf 225 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x03), 2);
sigveseb 0:6ac5ba1343bf 226
sigveseb 0:6ac5ba1343bf 227 wait_ms(30);
sigveseb 0:6ac5ba1343bf 228
sigveseb 0:6ac5ba1343bf 229 // Vcom driver on
sigveseb 0:6ac5ba1343bf 230 wait_us(10);
sigveseb 0:6ac5ba1343bf 231 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
sigveseb 0:6ac5ba1343bf 232 wait_us(10);
sigveseb 0:6ac5ba1343bf 233 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x0f), 2);
sigveseb 0:6ac5ba1343bf 234
sigveseb 0:6ac5ba1343bf 235 wait_ms(30);
sigveseb 0:6ac5ba1343bf 236
sigveseb 0:6ac5ba1343bf 237 // output enable to disable
sigveseb 0:6ac5ba1343bf 238 wait_us(10);
sigveseb 0:6ac5ba1343bf 239 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x02), 2);
sigveseb 0:6ac5ba1343bf 240 wait_us(10);
sigveseb 0:6ac5ba1343bf 241 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x24), 2);
sigveseb 0:6ac5ba1343bf 242 }
sigveseb 0:6ac5ba1343bf 243
sigveseb 0:6ac5ba1343bf 244
sigveseb 0:6ac5ba1343bf 245 void EPD_Class::end()
sigveseb 0:6ac5ba1343bf 246 {
sigveseb 0:6ac5ba1343bf 247 // dummy frame
sigveseb 0:6ac5ba1343bf 248 //this->frame_fixed(0x55, EPD_normal);
sigveseb 0:6ac5ba1343bf 249 // dummy line and border
sigveseb 0:6ac5ba1343bf 250 if (EPD_1_44 == this->size) {
sigveseb 0:6ac5ba1343bf 251 // only for 1.44" EPD
sigveseb 0:6ac5ba1343bf 252 this->line(0x7fffu, 0, 0xaa, false, EPD_normal);
sigveseb 0:6ac5ba1343bf 253
sigveseb 0:6ac5ba1343bf 254 wait_ms(250);
sigveseb 0:6ac5ba1343bf 255
sigveseb 0:6ac5ba1343bf 256 }
sigveseb 0:6ac5ba1343bf 257 else {
sigveseb 0:6ac5ba1343bf 258 // all other display sizes
sigveseb 0:6ac5ba1343bf 259 this->line(0x7fffu, 0, 0x55, false, EPD_normal);
sigveseb 0:6ac5ba1343bf 260
sigveseb 0:6ac5ba1343bf 261 wait_ms(25);
sigveseb 0:6ac5ba1343bf 262
sigveseb 0:6ac5ba1343bf 263 this->EPD_Pin_BORDER = 0;
sigveseb 0:6ac5ba1343bf 264 wait_ms(250);
sigveseb 0:6ac5ba1343bf 265 this->EPD_Pin_BORDER = 1;
sigveseb 0:6ac5ba1343bf 266 }
sigveseb 0:6ac5ba1343bf 267 SPI_on();
sigveseb 0:6ac5ba1343bf 268 // latch reset turn on
sigveseb 0:6ac5ba1343bf 269 wait_us(10);
sigveseb 0:6ac5ba1343bf 270 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x03), 2);
sigveseb 0:6ac5ba1343bf 271 wait_us(10);
sigveseb 0:6ac5ba1343bf 272 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x01), 2);
sigveseb 0:6ac5ba1343bf 273
sigveseb 0:6ac5ba1343bf 274 // output enable off
sigveseb 0:6ac5ba1343bf 275 wait_us(10);
sigveseb 0:6ac5ba1343bf 276 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x02), 2);
sigveseb 0:6ac5ba1343bf 277 wait_us(10);
sigveseb 0:6ac5ba1343bf 278 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x05), 2);
sigveseb 0:6ac5ba1343bf 279
sigveseb 0:6ac5ba1343bf 280 // Vcom power off
sigveseb 0:6ac5ba1343bf 281 wait_us(10);
sigveseb 0:6ac5ba1343bf 282 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
sigveseb 0:6ac5ba1343bf 283 wait_us(10);
sigveseb 0:6ac5ba1343bf 284 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x0e), 2);
sigveseb 0:6ac5ba1343bf 285
sigveseb 0:6ac5ba1343bf 286 // power off negative charge pump
sigveseb 0:6ac5ba1343bf 287 wait_us(10);
sigveseb 0:6ac5ba1343bf 288 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
sigveseb 0:6ac5ba1343bf 289 wait_us(10);
sigveseb 0:6ac5ba1343bf 290 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x02), 2);
sigveseb 0:6ac5ba1343bf 291
sigveseb 0:6ac5ba1343bf 292 // discharge
sigveseb 0:6ac5ba1343bf 293 wait_us(10);
sigveseb 0:6ac5ba1343bf 294 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
sigveseb 0:6ac5ba1343bf 295 wait_us(10);
sigveseb 0:6ac5ba1343bf 296 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x0c), 2);
sigveseb 0:6ac5ba1343bf 297
sigveseb 0:6ac5ba1343bf 298 wait_ms(120);
sigveseb 0:6ac5ba1343bf 299
sigveseb 0:6ac5ba1343bf 300 // all charge pumps off
sigveseb 0:6ac5ba1343bf 301 wait_us(10);
sigveseb 0:6ac5ba1343bf 302 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
sigveseb 0:6ac5ba1343bf 303 wait_us(10);
sigveseb 0:6ac5ba1343bf 304 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x00), 2);
sigveseb 0:6ac5ba1343bf 305
sigveseb 0:6ac5ba1343bf 306 // turn of osc
sigveseb 0:6ac5ba1343bf 307 wait_us(10);
sigveseb 0:6ac5ba1343bf 308 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x07), 2);
sigveseb 0:6ac5ba1343bf 309 wait_us(10);
sigveseb 0:6ac5ba1343bf 310 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x0d), 2);
sigveseb 0:6ac5ba1343bf 311
sigveseb 0:6ac5ba1343bf 312 // discharge internal - 1
sigveseb 0:6ac5ba1343bf 313 wait_us(10);
sigveseb 0:6ac5ba1343bf 314 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
sigveseb 0:6ac5ba1343bf 315 wait_us(10);
sigveseb 0:6ac5ba1343bf 316 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x50), 2);
sigveseb 0:6ac5ba1343bf 317
sigveseb 0:6ac5ba1343bf 318 wait_ms(40);
sigveseb 0:6ac5ba1343bf 319
sigveseb 0:6ac5ba1343bf 320 // discharge internal - 2
sigveseb 0:6ac5ba1343bf 321 wait_us(10);
sigveseb 0:6ac5ba1343bf 322 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
sigveseb 0:6ac5ba1343bf 323 wait_us(10);
sigveseb 0:6ac5ba1343bf 324 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0xA0), 2);
sigveseb 0:6ac5ba1343bf 325
sigveseb 0:6ac5ba1343bf 326 wait_ms(40);
sigveseb 0:6ac5ba1343bf 327
sigveseb 0:6ac5ba1343bf 328 // discharge internal - 3
sigveseb 0:6ac5ba1343bf 329 wait_us(10);
sigveseb 0:6ac5ba1343bf 330 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
sigveseb 0:6ac5ba1343bf 331 wait_us(10);
sigveseb 0:6ac5ba1343bf 332 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x00), 2);
sigveseb 0:6ac5ba1343bf 333 // turn of power and all signals
sigveseb 0:6ac5ba1343bf 334 //
sigveseb 0:6ac5ba1343bf 335
sigveseb 0:6ac5ba1343bf 336 wait_ms(10);
sigveseb 0:6ac5ba1343bf 337 this->EPD_Pin_RESET = 0;
sigveseb 0:6ac5ba1343bf 338 this->EPD_Pin_PANEL_ON = 0;
sigveseb 0:6ac5ba1343bf 339 this->EPD_Pin_BORDER = 0;
sigveseb 0:6ac5ba1343bf 340
sigveseb 0:6ac5ba1343bf 341 // discharge pulse
sigveseb 0:6ac5ba1343bf 342 this->EPD_Pin_DISCHARGE = 1;
sigveseb 0:6ac5ba1343bf 343 wait_ms(250);
sigveseb 0:6ac5ba1343bf 344 this->EPD_Pin_DISCHARGE = 0;
sigveseb 0:6ac5ba1343bf 345
sigveseb 0:6ac5ba1343bf 346 EPD_Pin_EPD_CS = 1;
sigveseb 0:6ac5ba1343bf 347 }
sigveseb 0:6ac5ba1343bf 348
sigveseb 0:6ac5ba1343bf 349
sigveseb 0:6ac5ba1343bf 350 // convert a temperature in Celcius to
sigveseb 0:6ac5ba1343bf 351 // the scale factor for frame_*_repeat methods
sigveseb 0:6ac5ba1343bf 352 int EPD_Class::temperature_to_factor_10x(int temperature)
sigveseb 0:6ac5ba1343bf 353 {
sigveseb 0:6ac5ba1343bf 354 if (temperature <= -10) {
sigveseb 0:6ac5ba1343bf 355 return 170;
sigveseb 0:6ac5ba1343bf 356 } else if (temperature <= -5) {
sigveseb 0:6ac5ba1343bf 357 return 120;
sigveseb 0:6ac5ba1343bf 358 } else if (temperature <= 5) {
sigveseb 0:6ac5ba1343bf 359 return 80;
sigveseb 0:6ac5ba1343bf 360 } else if (temperature <= 10) {
sigveseb 0:6ac5ba1343bf 361 return 40;
sigveseb 0:6ac5ba1343bf 362 } else if (temperature <= 15) {
sigveseb 0:6ac5ba1343bf 363 return 30;
sigveseb 0:6ac5ba1343bf 364 } else if (temperature <= 20) {
sigveseb 0:6ac5ba1343bf 365 return 20;
sigveseb 0:6ac5ba1343bf 366 } else if (temperature <= 40) {
sigveseb 0:6ac5ba1343bf 367 return 10;
sigveseb 0:6ac5ba1343bf 368 }
sigveseb 0:6ac5ba1343bf 369 return 7;
sigveseb 0:6ac5ba1343bf 370 }
sigveseb 0:6ac5ba1343bf 371
sigveseb 0:6ac5ba1343bf 372
sigveseb 0:6ac5ba1343bf 373 // One frame of data is the number of lines * rows. For example:
sigveseb 0:6ac5ba1343bf 374 // The 1.44” frame of data is 96 lines * 128 dots.
sigveseb 0:6ac5ba1343bf 375 // The 2” frame of data is 96 lines * 200 dots.
sigveseb 0:6ac5ba1343bf 376 // The 2.7” frame of data is 176 lines * 264 dots.
sigveseb 0:6ac5ba1343bf 377
sigveseb 0:6ac5ba1343bf 378 // the image is arranged by line which matches the display size
sigveseb 0:6ac5ba1343bf 379 // so smallest would have 96 * 32 bytes
sigveseb 0:6ac5ba1343bf 380
sigveseb 0:6ac5ba1343bf 381 void EPD_Class::frame_fixed(uint8_t fixed_value, EPD_stage stage, int from_line, int to_line)
sigveseb 0:6ac5ba1343bf 382 {
sigveseb 0:6ac5ba1343bf 383 for (uint8_t line = from_line; line < to_line; line++)
sigveseb 0:6ac5ba1343bf 384 {
sigveseb 0:6ac5ba1343bf 385 this->line(line, 0, fixed_value, false, stage);
sigveseb 0:6ac5ba1343bf 386 }
sigveseb 0:6ac5ba1343bf 387 }
sigveseb 0:6ac5ba1343bf 388
sigveseb 0:6ac5ba1343bf 389 void EPD_Class::frame_data(const uint8_t *image, EPD_stage stage, int from_line, int to_line)
sigveseb 0:6ac5ba1343bf 390 {
sigveseb 0:6ac5ba1343bf 391 for (uint8_t line = from_line; line < to_line; line++)
sigveseb 0:6ac5ba1343bf 392 {
sigveseb 0:6ac5ba1343bf 393 this->line(line, &image[line * this->bytes_per_line], 0, true, stage);
sigveseb 0:6ac5ba1343bf 394 }
sigveseb 0:6ac5ba1343bf 395 }
sigveseb 0:6ac5ba1343bf 396
sigveseb 0:6ac5ba1343bf 397
sigveseb 0:6ac5ba1343bf 398 void EPD_Class::frame_fixed_repeat(uint8_t fixed_value, EPD_stage stage, int from_line, int to_line)
sigveseb 0:6ac5ba1343bf 399 {
sigveseb 0:6ac5ba1343bf 400 long stage_time = this->factored_stage_time;
sigveseb 0:6ac5ba1343bf 401 do {
sigveseb 0:6ac5ba1343bf 402 unsigned long t_start = timer.read_ms();
sigveseb 0:6ac5ba1343bf 403 this->frame_fixed(fixed_value, stage, from_line, to_line);
sigveseb 0:6ac5ba1343bf 404 unsigned long t_end = timer.read_ms();
sigveseb 0:6ac5ba1343bf 405 if (t_end > t_start) {
sigveseb 0:6ac5ba1343bf 406 stage_time -= t_end - t_start;
sigveseb 0:6ac5ba1343bf 407 } else {
sigveseb 0:6ac5ba1343bf 408 stage_time -= t_start - t_end + 1 + ULONG_MAX;
sigveseb 0:6ac5ba1343bf 409 }
sigveseb 0:6ac5ba1343bf 410 } while (stage_time > 0);
sigveseb 0:6ac5ba1343bf 411 }
sigveseb 0:6ac5ba1343bf 412
sigveseb 0:6ac5ba1343bf 413
sigveseb 0:6ac5ba1343bf 414 void EPD_Class::frame_data_repeat(const uint8_t *image, EPD_stage stage, int from_line, int to_line)
sigveseb 0:6ac5ba1343bf 415 {
sigveseb 0:6ac5ba1343bf 416
sigveseb 0:6ac5ba1343bf 417 long stage_time = this->factored_stage_time;
sigveseb 0:6ac5ba1343bf 418
sigveseb 0:6ac5ba1343bf 419 do {
sigveseb 0:6ac5ba1343bf 420 unsigned long t_start = timer.read_ms();
sigveseb 0:6ac5ba1343bf 421 this->frame_data(image, stage, from_line, to_line);
sigveseb 0:6ac5ba1343bf 422 unsigned long t_end = timer.read_ms();
sigveseb 0:6ac5ba1343bf 423 if (t_end > t_start) {
sigveseb 0:6ac5ba1343bf 424 stage_time -= t_end - t_start;
sigveseb 0:6ac5ba1343bf 425 } else {
sigveseb 0:6ac5ba1343bf 426 stage_time -= t_start - t_end + 1 + ULONG_MAX;
sigveseb 0:6ac5ba1343bf 427 }
sigveseb 0:6ac5ba1343bf 428 } while (stage_time > 0);
sigveseb 0:6ac5ba1343bf 429
sigveseb 0:6ac5ba1343bf 430 }
sigveseb 0:6ac5ba1343bf 431
sigveseb 0:6ac5ba1343bf 432 void EPD_Class::line(uint16_t line, const uint8_t *data, uint8_t fixed_value, bool read_progmem, EPD_stage stage)
sigveseb 0:6ac5ba1343bf 433 {
sigveseb 0:6ac5ba1343bf 434 // charge pump voltage levels
sigveseb 0:6ac5ba1343bf 435 SPI_on();
sigveseb 0:6ac5ba1343bf 436 wait_us(10);
sigveseb 0:6ac5ba1343bf 437 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
sigveseb 0:6ac5ba1343bf 438 wait_us(10);
sigveseb 0:6ac5ba1343bf 439 SPI_send(this->EPD_Pin_EPD_CS, this->gate_source, this->gate_source_length);
sigveseb 0:6ac5ba1343bf 440
sigveseb 0:6ac5ba1343bf 441 // send data
sigveseb 0:6ac5ba1343bf 442 wait_us(10);
sigveseb 0:6ac5ba1343bf 443 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x0a), 2);
sigveseb 0:6ac5ba1343bf 444 wait_us(10);
sigveseb 0:6ac5ba1343bf 445
sigveseb 0:6ac5ba1343bf 446 // CS low
sigveseb 0:6ac5ba1343bf 447 this->EPD_Pin_EPD_CS = 0;
sigveseb 0:6ac5ba1343bf 448 SPI_put_wait(0x72, this->EPD_Pin_BUSY);
sigveseb 0:6ac5ba1343bf 449
sigveseb 0:6ac5ba1343bf 450 // even pixels
sigveseb 0:6ac5ba1343bf 451 for (uint16_t b = this->bytes_per_line; b > 0; --b)
sigveseb 0:6ac5ba1343bf 452 {
sigveseb 0:6ac5ba1343bf 453 if (0 != data)
sigveseb 0:6ac5ba1343bf 454 {
sigveseb 0:6ac5ba1343bf 455
sigveseb 0:6ac5ba1343bf 456 uint8_t pixels = data[b - 1] & 0xaa;
sigveseb 0:6ac5ba1343bf 457
sigveseb 0:6ac5ba1343bf 458
sigveseb 0:6ac5ba1343bf 459 switch(stage)
sigveseb 0:6ac5ba1343bf 460 {
sigveseb 0:6ac5ba1343bf 461 case EPD_compensate: // B -> W, W -> B (Current Image)
sigveseb 0:6ac5ba1343bf 462 pixels = 0xaa | ((pixels ^ 0xaa) >> 1);
sigveseb 0:6ac5ba1343bf 463 break;
sigveseb 0:6ac5ba1343bf 464
sigveseb 0:6ac5ba1343bf 465 case EPD_white: // B -> N, W -> W (Current Image)
sigveseb 0:6ac5ba1343bf 466 pixels = 0x55 + ((pixels ^ 0xaa) >> 1);
sigveseb 0:6ac5ba1343bf 467 break;
sigveseb 0:6ac5ba1343bf 468
sigveseb 0:6ac5ba1343bf 469 case EPD_inverse: // B -> N, W -> B (New Image)
sigveseb 0:6ac5ba1343bf 470 pixels = 0x55 | (pixels ^ 0xaa);
sigveseb 0:6ac5ba1343bf 471 break;
sigveseb 0:6ac5ba1343bf 472
sigveseb 0:6ac5ba1343bf 473 case EPD_normal: // B -> B, W -> W (New Image)
sigveseb 0:6ac5ba1343bf 474 pixels = 0xaa | (pixels >> 1);
sigveseb 0:6ac5ba1343bf 475 break;
sigveseb 0:6ac5ba1343bf 476 }
sigveseb 0:6ac5ba1343bf 477
sigveseb 0:6ac5ba1343bf 478 SPI_put_wait(pixels, this->EPD_Pin_BUSY);
sigveseb 0:6ac5ba1343bf 479 //wait_us(1);
sigveseb 0:6ac5ba1343bf 480 }
sigveseb 0:6ac5ba1343bf 481 else
sigveseb 0:6ac5ba1343bf 482 {
sigveseb 0:6ac5ba1343bf 483 SPI_put_wait(fixed_value, this->EPD_Pin_BUSY);
sigveseb 0:6ac5ba1343bf 484 //wait_ms(1);
sigveseb 0:6ac5ba1343bf 485 }
sigveseb 0:6ac5ba1343bf 486 }
sigveseb 0:6ac5ba1343bf 487
sigveseb 0:6ac5ba1343bf 488 // scan line
sigveseb 0:6ac5ba1343bf 489 for (uint16_t b = 0; b < this->bytes_per_scan; ++b)
sigveseb 0:6ac5ba1343bf 490 {
sigveseb 0:6ac5ba1343bf 491 if (line / 4 == b)
sigveseb 0:6ac5ba1343bf 492 {
sigveseb 0:6ac5ba1343bf 493 SPI_put_wait(0xc0 >> (2 * (line & 0x03)), this->EPD_Pin_BUSY);
sigveseb 0:6ac5ba1343bf 494 }
sigveseb 0:6ac5ba1343bf 495 else
sigveseb 0:6ac5ba1343bf 496 {
sigveseb 0:6ac5ba1343bf 497 SPI_put_wait(0x00, this->EPD_Pin_BUSY);
sigveseb 0:6ac5ba1343bf 498 }
sigveseb 0:6ac5ba1343bf 499 //wait_ms(10);
sigveseb 0:6ac5ba1343bf 500 }
sigveseb 0:6ac5ba1343bf 501
sigveseb 0:6ac5ba1343bf 502 // odd pixels
sigveseb 0:6ac5ba1343bf 503 for (uint16_t b = 0; b < this->bytes_per_line; ++b)
sigveseb 0:6ac5ba1343bf 504 {
sigveseb 0:6ac5ba1343bf 505 if (0 != data)
sigveseb 0:6ac5ba1343bf 506 {
sigveseb 0:6ac5ba1343bf 507 uint8_t pixels = data[b] & 0x55;
sigveseb 0:6ac5ba1343bf 508
sigveseb 0:6ac5ba1343bf 509
sigveseb 0:6ac5ba1343bf 510 switch(stage)
sigveseb 0:6ac5ba1343bf 511 {
sigveseb 0:6ac5ba1343bf 512 case EPD_compensate: // B -> W, W -> B (Current Image)
sigveseb 0:6ac5ba1343bf 513 pixels = 0xaa | (pixels ^ 0x55);
sigveseb 0:6ac5ba1343bf 514 break;
sigveseb 0:6ac5ba1343bf 515 case EPD_white: // B -> N, W -> W (Current Image)
sigveseb 0:6ac5ba1343bf 516 pixels = 0x55 + (pixels ^ 0x55);
sigveseb 0:6ac5ba1343bf 517 break;
sigveseb 0:6ac5ba1343bf 518 case EPD_inverse: // B -> N, W -> B (New Image)
sigveseb 0:6ac5ba1343bf 519 pixels = 0x55 | ((pixels ^ 0x55) << 1);
sigveseb 0:6ac5ba1343bf 520 break;
sigveseb 0:6ac5ba1343bf 521 case EPD_normal: // B -> B, W -> W (New Image)
sigveseb 0:6ac5ba1343bf 522 pixels = 0xaa | pixels;
sigveseb 0:6ac5ba1343bf 523 break;
sigveseb 0:6ac5ba1343bf 524 }
sigveseb 0:6ac5ba1343bf 525 uint8_t p1 = (pixels >> 6) & 0x03;
sigveseb 0:6ac5ba1343bf 526 uint8_t p2 = (pixels >> 4) & 0x03;
sigveseb 0:6ac5ba1343bf 527 uint8_t p3 = (pixels >> 2) & 0x03;
sigveseb 0:6ac5ba1343bf 528 uint8_t p4 = (pixels >> 0) & 0x03;
sigveseb 0:6ac5ba1343bf 529 pixels = (p1 << 0) | (p2 << 2) | (p3 << 4) | (p4 << 6);
sigveseb 0:6ac5ba1343bf 530 SPI_put_wait(pixels, this->EPD_Pin_BUSY);
sigveseb 0:6ac5ba1343bf 531 }
sigveseb 0:6ac5ba1343bf 532 else
sigveseb 0:6ac5ba1343bf 533 {
sigveseb 0:6ac5ba1343bf 534 SPI_put_wait(fixed_value, this->EPD_Pin_BUSY);
sigveseb 0:6ac5ba1343bf 535 }
sigveseb 0:6ac5ba1343bf 536 //wait_ms(10);
sigveseb 0:6ac5ba1343bf 537 }
sigveseb 0:6ac5ba1343bf 538
sigveseb 0:6ac5ba1343bf 539 if (this->filler)
sigveseb 0:6ac5ba1343bf 540 {
sigveseb 0:6ac5ba1343bf 541 SPI_put_wait(0x00, this->EPD_Pin_BUSY);
sigveseb 0:6ac5ba1343bf 542 }
sigveseb 0:6ac5ba1343bf 543
sigveseb 0:6ac5ba1343bf 544 // CS high
sigveseb 0:6ac5ba1343bf 545 this->EPD_Pin_EPD_CS = 1;
sigveseb 0:6ac5ba1343bf 546
sigveseb 0:6ac5ba1343bf 547 // output data to panel
sigveseb 0:6ac5ba1343bf 548 wait_us(10);
sigveseb 0:6ac5ba1343bf 549 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x02), 2);
sigveseb 0:6ac5ba1343bf 550 wait_us(10);
sigveseb 0:6ac5ba1343bf 551 SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x2f), 2);
sigveseb 0:6ac5ba1343bf 552 }
sigveseb 0:6ac5ba1343bf 553
sigveseb 0:6ac5ba1343bf 554 static void SPI_on() {
sigveseb 0:6ac5ba1343bf 555 wait_us(10);
sigveseb 0:6ac5ba1343bf 556 }
sigveseb 0:6ac5ba1343bf 557
sigveseb 0:6ac5ba1343bf 558
sigveseb 0:6ac5ba1343bf 559 static void SPI_put(uint8_t c) {
sigveseb 0:6ac5ba1343bf 560 spi.write(c);
sigveseb 0:6ac5ba1343bf 561 }
sigveseb 0:6ac5ba1343bf 562
sigveseb 0:6ac5ba1343bf 563
sigveseb 0:6ac5ba1343bf 564 static void SPI_put_wait(uint8_t c, DigitalIn busy_pin) {
sigveseb 0:6ac5ba1343bf 565
sigveseb 0:6ac5ba1343bf 566 SPI_put(c);
sigveseb 0:6ac5ba1343bf 567
sigveseb 0:6ac5ba1343bf 568 // wait for COG ready
sigveseb 0:6ac5ba1343bf 569 while (1 == busy_pin) {
sigveseb 0:6ac5ba1343bf 570 }
sigveseb 0:6ac5ba1343bf 571 }
sigveseb 0:6ac5ba1343bf 572
sigveseb 0:6ac5ba1343bf 573
sigveseb 0:6ac5ba1343bf 574 static void SPI_send(DigitalOut cs_pin, const uint8_t *buffer, uint16_t length) {
sigveseb 0:6ac5ba1343bf 575 // CS low
sigveseb 0:6ac5ba1343bf 576 cs_pin = 0;
sigveseb 0:6ac5ba1343bf 577
sigveseb 0:6ac5ba1343bf 578 // send all data
sigveseb 0:6ac5ba1343bf 579 for (uint16_t i = 0; i < length; ++i) {
sigveseb 0:6ac5ba1343bf 580 SPI_put(*buffer++);
sigveseb 0:6ac5ba1343bf 581 }
sigveseb 0:6ac5ba1343bf 582
sigveseb 0:6ac5ba1343bf 583 // CS high
sigveseb 0:6ac5ba1343bf 584 cs_pin = 1;
sigveseb 0:6ac5ba1343bf 585 }