Come from standard seeed epaper, but adding SPI signal in construtor

Fork of seeedstudio-epaper by Nordic Pucks

Committer:
thierryc49
Date:
Fri Nov 13 20:46:53 2015 +0000
Revision:
2:c5bb7d34974d
Parent:
1:2f62e2b80305
lib from seedstudio-epaper, Add SPI in parameter's constructor

Who changed what in which revision?

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