epaper

Dependents:   epaper_mbed_test_copy1

Fork of EaEpaper by Peter Drescher

Committer:
dreschpe
Date:
Sat Nov 09 23:37:43 2013 +0000
Revision:
0:fedcef5319f5
Lib for using a E-Paper display from Pervasive Displays.; There is a interface board from Embedded Artists.; It can handle graphic and text drawing and is using external fonts.

Who changed what in which revision?

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