A lib to handle a E-Paper display from Pervasive Displays. There is a interface board from Embedded Artists. The lib can handle graphic and text drawing and is using external fonts.

Dependents:   epaper_mbed_130411_KL25Z epaper_mbed_test epaper_KL25Z_2 test_he10 ... more

/media/uploads/dreschpe/epaper.jpg

The E-Paper display from Pervasive Displays with a interface board is available from Embedded Artists : http://www.embeddedartists.com/products/displays/lcd_27_epaper.php The 2.7 inch display have 264*176 pixel, monochrome.

Technology

You can look at the webside from Pervasive to see how the display works. http://www.pervasivedisplays.com/technology/home

This type of display have ultra low power consumption - due to its bi-stable nature. It requires only very little power to update the display and needs no power to maintain an image. You can disconnect the display - the image is still there. The viewing angle is like real paper - near 180°.

There are also some disadvantages of this technology. To change the image, we have to rewrite the full display in 4 steps. Invert, clear, invert new, new image. This process is visible and take a while -2s at room temperature. If it gets colder the display reacts slower and the interface timing has to be slow down. To compensate this, there is a LM75 temp sensor on the interface board. We also need ram to double buffer the display. 264 * 176 / 8 = 5808 Byte. To double buffer we need 11616 byte of ram. This is no problem for most mbed devices, but it will not run on the LPC11U24 or LPC800-MAX.

Interface

The graphic data is transferred to the display via spi. The maximum speed is 12Mhz. There are also some control signal and the I2C for the temperature sensor. Together we need 12 signals.

Displaymbed LPC1768mbed KL25Zsignal type
1 GNDGNDGNDGND
2 3V3VOUTP3V33.3 V power
3 SCKp7PTD1SCK
4 MOSIp5PTD2MOSI
5 MISOp6PTD3MISO
6 SSELp8PTC17GPIO
7 Busyp13PTA16GPIO
8 Borderp10PTD6GPIO
9 SCLp27PTE1SCL
10 SDAp28PTE0SDA
11 PWMp26PTD4PWM
12 Resetp12PTA17GPIO
13 Power controlp9PTD7GPIO
14 Dischargep11PTE31GPIO

Software

Fonts

How to get nice looking fonts ?

To print characters to a graphic screen we need a font. To code a font by paper is ok for a small lcd, but for a 264*176 pixel display we need bigger fonts. A 12*12 pixel font is readable, but it a lot of work to construct it by hand.

Fonts can be made with the GLCD Font Creator also from http://www.mikroe.com .

With this program you can load a window font and convert it into a c-array. To use this Font with my lib you have to add 4 parameter at the beginning of the font array. - the number of byte / char - the vertial size in pixel - the horizontal size in pixel - the number of byte per vertical line (it is vertical size / 8 ) You also have to change the type of array to char[]. After that you can switch between different fonts with set_font(unsigned char* font); The horizontal size of each character is also stored in the font. It look better if you use bigger fonts or italic. The letter M is wider than a l.

Here are some Fonts from me : http://mbed.org/users/dreschpe/code/TFT_fonts/

The small made for the mbed lab board can also be used : http://mbed.org/users/dreschpe/code/LCD_fonts/

And from Peter Holzleitner : http://mbed.org/users/pholzleitner/code/SourceCodePro31-SB/

Text commands :

You can use the claim() function to redirect the output to stdout or stderr to the display. After claim(stdout) you can simply use the printf function without the classname to print to the display. All other printf from other libs are also redirected to the display if you use this.

  • printf(...); print text and variables to the buffer with format options.
  • locate(x,y); function is used to setup the cursor position. x,y are the pixel position.

Graphics

Graphic commands :

  • cls(); Fill the screen with background color
  • pixel(x,y,color); set a single pixel at x,y with 1 : black or 0 : white
  • line(x0,y0,x1,y1,color); draw a line from x0,y0 to x1,y1 with color
  • rect(x0,y0,x1,y1,color); draw a rectangle x0,y0 to x1,y1 with color
  • fillrect(x0,y0,x1,y1,color); draw a filled rectangle
  • circle( x0,y0,radius ,color); draw a circle around x0,y0 with radius
  • fillcircle(x0,y0,radius ,color); draw a filled circle around x0,y0 with radius
  • setmode(mode); Set the drawing mode for all functions. mode can be NORMAL -> 0 is white and 1 is black or XOR -> the new pixel is a xor between the old display and the new. This mode will invert if a black pixel is draw over a black pixel.
  • print_bm(Bitmap ,x0,x0); Print a monochrome bitmap array. This graphic is defined by a Bitmap struct :

The pixel date array :

static char arm_logo[]={
0x00,0x00...
};

and a Bitmap struct:

Bitmap bitmARM = {
  48, // XSize
  48, // YSize 
  6,  // Bytes in Line
  arm_logo // Pointer to picture data 
};

To convert a graphic into a byte array we can use the tool Picture Converter 1bpp from http://www.embedded-tools.de.vu/ With this tool we load a image, press the convert button and save it as C-Header file. We have to save with horizontal orientation, so we have to press "No". Inside this file we find the data array which we can copy into a header file.

All this commands are writing to the frame buffer only ! To change the active display we have to call

  • write_disp(); This will refresh the display.

Sample code

test code for the LPC1768: http://mbed.org/users/dreschpe/code/epaper_mbed_test/

test code for KL25Z: http://mbed.org/users/dreschpe/code/epaper_mbed_130411_KL25Z/

#include "mbed.h"
#include "EaEpaper.h"
#include "Arial28x28.h"
#include "Arial12x12.h"
#include "font_big.h"
#include "graphics.h"

EaEpaper epaper(
                PTD7,            // PWR_CTRL
                PTD6,            // BORDER
                PTE31,           // DISCHARGE
                PTA17,           // RESET_DISP
                PTA16,           // BUSY
                PTC17,           // SSEL
                PTD4,            // PWM
                PTD2,PTD3,PTD1,  // MOSI,MISO,SCLK
                PTE0,PTE1);      // SDA,SDL 
 
int main() {

    epaper.cls();                                      // clear screen
    epaper.set_font((unsigned char*) Arial28x28);  // select the font
    epaper.locate(5,20);                           // set cursor
    epaper.printf("Hello Mbed");                  // print  text
    epaper.rect(3,15,150,50,1);                  // print a frame 
     
    epaper.set_font((unsigned char*) Arial12x12);  // change font
    epaper.locate(5,60);                               // set cursor
    epaper.printf("small Font");                    // print text
    epaper.set_font((unsigned char*) Neu42x35);  // change font
    epaper.locate(5,70);                               //set cursor
    epaper.printf("big Font");                        // change font
    
    epaper.write_disp(); // update screen       // update display
    
    wait(5);                                           // wait 5 s
    epaper.fillcircle(180,30,22,1);              // paint filled circle
    epaper.circle(160,150,20,1);               // paint circle
    epaper.write_disp(); // update screen      // update display
    
}
  
Committer:
dreschpe
Date:
Sat Nov 09 23:37:43 2013 +0000
Revision:
0:fedcef5319f5
Child:
3:1371614703cd
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 //}