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 #ifndef EPD_H
dreschpe 0:fedcef5319f5 16 #define EPD_H
dreschpe 0:fedcef5319f5 17
dreschpe 0:fedcef5319f5 18 #include "mbed.h"
dreschpe 0:fedcef5319f5 19 #include "BurstSPI.h"
dreschpe 0:fedcef5319f5 20
dreschpe 0:fedcef5319f5 21 #define PROGMEM
dreschpe 0:fedcef5319f5 22
dreschpe 0:fedcef5319f5 23
dreschpe 0:fedcef5319f5 24 typedef enum {
dreschpe 0:fedcef5319f5 25 EPD_1_44, // 128 x 96
dreschpe 0:fedcef5319f5 26 EPD_2_0, // 200 x 96
dreschpe 0:fedcef5319f5 27 EPD_2_7 // 264 x 176
dreschpe 0:fedcef5319f5 28 } EPD_size;
dreschpe 0:fedcef5319f5 29
dreschpe 0:fedcef5319f5 30 typedef enum { // Image pixel -> Display pixel
dreschpe 0:fedcef5319f5 31 EPD_compensate, // B -> W, W -> B (Current Image)
dreschpe 0:fedcef5319f5 32 EPD_white, // B -> N, W -> W (Current Image)
dreschpe 0:fedcef5319f5 33 EPD_inverse, // B -> N, W -> B (New Image)
dreschpe 0:fedcef5319f5 34 EPD_normal // B -> B, W -> W (New Image)
dreschpe 0:fedcef5319f5 35 } EPD_stage;
dreschpe 0:fedcef5319f5 36
dreschpe 0:fedcef5319f5 37 typedef void EPD_reader(void *buffer, uint32_t address, uint16_t length);
dreschpe 0:fedcef5319f5 38
dreschpe 0:fedcef5319f5 39 class EPD_Class {
dreschpe 0:fedcef5319f5 40 private:
dreschpe 0:fedcef5319f5 41 DigitalOut EPD_Pin_PANEL_ON;
dreschpe 0:fedcef5319f5 42 DigitalOut EPD_Pin_BORDER;
dreschpe 0:fedcef5319f5 43 DigitalOut EPD_Pin_DISCHARGE;
dreschpe 0:fedcef5319f5 44 PwmOut EPD_Pin_PWM;
dreschpe 0:fedcef5319f5 45 DigitalOut EPD_Pin_RESET;
dreschpe 0:fedcef5319f5 46 DigitalIn EPD_Pin_BUSY;
dreschpe 0:fedcef5319f5 47 DigitalOut EPD_Pin_EPD_CS;
dreschpe 0:fedcef5319f5 48 BurstSPI spi_;
dreschpe 0:fedcef5319f5 49
dreschpe 0:fedcef5319f5 50 EPD_size size;
dreschpe 0:fedcef5319f5 51 uint16_t stage_time;
dreschpe 0:fedcef5319f5 52 uint16_t factored_stage_time;
dreschpe 0:fedcef5319f5 53 uint16_t lines_per_display;
dreschpe 0:fedcef5319f5 54 uint16_t dots_per_line;
dreschpe 0:fedcef5319f5 55 uint16_t bytes_per_line;
dreschpe 0:fedcef5319f5 56 uint16_t bytes_per_scan;
dreschpe 0:fedcef5319f5 57 PROGMEM const uint8_t *gate_source;
dreschpe 0:fedcef5319f5 58 uint16_t gate_source_length;
dreschpe 0:fedcef5319f5 59 PROGMEM const uint8_t *channel_select;
dreschpe 0:fedcef5319f5 60 uint16_t channel_select_length;
dreschpe 0:fedcef5319f5 61
dreschpe 0:fedcef5319f5 62 bool filler;
dreschpe 0:fedcef5319f5 63
dreschpe 0:fedcef5319f5 64 void SPI_put(uint8_t c);
dreschpe 0:fedcef5319f5 65 void SPI_put_wait(uint8_t c, DigitalIn busy_pin);
dreschpe 0:fedcef5319f5 66 void SPI_send(DigitalOut cs_pin, const uint8_t *buffer, uint16_t length);
dreschpe 0:fedcef5319f5 67
dreschpe 0:fedcef5319f5 68 public:
dreschpe 0:fedcef5319f5 69 // power up and power down the EPD panel
dreschpe 0:fedcef5319f5 70 void begin();
dreschpe 0:fedcef5319f5 71 void end();
dreschpe 0:fedcef5319f5 72
dreschpe 0:fedcef5319f5 73 void setFactor(int temperature = 25) {
dreschpe 0:fedcef5319f5 74 this->factored_stage_time = this->stage_time * this->temperature_to_factor_10x(temperature) / 10;
dreschpe 0:fedcef5319f5 75 }
dreschpe 0:fedcef5319f5 76
dreschpe 0:fedcef5319f5 77 // clear display (anything -> white)
dreschpe 0:fedcef5319f5 78 void clear() {
dreschpe 0:fedcef5319f5 79 this->frame_fixed_repeat(0xff, EPD_compensate);
dreschpe 0:fedcef5319f5 80 this->frame_fixed_repeat(0xff, EPD_white);
dreschpe 0:fedcef5319f5 81 this->frame_fixed_repeat(0xaa, EPD_inverse);
dreschpe 0:fedcef5319f5 82 this->frame_fixed_repeat(0xaa, EPD_normal);
dreschpe 0:fedcef5319f5 83 }
dreschpe 0:fedcef5319f5 84
dreschpe 0:fedcef5319f5 85 // assuming a clear (white) screen output an image (PROGMEM data)
dreschpe 0:fedcef5319f5 86 void image(const uint8_t *image) {
dreschpe 0:fedcef5319f5 87 this->frame_fixed_repeat(0xaa, EPD_compensate);
dreschpe 0:fedcef5319f5 88 this->frame_fixed_repeat(0xaa, EPD_white);
dreschpe 0:fedcef5319f5 89 this->frame_data_repeat(image, EPD_inverse);
dreschpe 0:fedcef5319f5 90 this->frame_data_repeat(image, EPD_normal);
dreschpe 0:fedcef5319f5 91 }
dreschpe 0:fedcef5319f5 92
dreschpe 0:fedcef5319f5 93 // change from old image to new image (PROGMEM data)
dreschpe 0:fedcef5319f5 94 void image(const uint8_t *old_image, const uint8_t *new_image) {
dreschpe 0:fedcef5319f5 95 this->frame_data_repeat(old_image, EPD_compensate);
dreschpe 0:fedcef5319f5 96 this->frame_data_repeat(old_image, EPD_white);
dreschpe 0:fedcef5319f5 97 this->frame_data_repeat(new_image, EPD_inverse);
dreschpe 0:fedcef5319f5 98 this->frame_data_repeat(new_image, EPD_normal);
dreschpe 0:fedcef5319f5 99 }
dreschpe 0:fedcef5319f5 100
dreschpe 0:fedcef5319f5 101 #if defined(EPD_ENABLE_EXTRA_SRAM)
dreschpe 0:fedcef5319f5 102
dreschpe 0:fedcef5319f5 103 // change from old image to new image (SRAM version)
dreschpe 0:fedcef5319f5 104 void image_sram(const uint8_t *old_image, const uint8_t *new_image) {
dreschpe 0:fedcef5319f5 105 this->frame_sram_repeat(old_image, EPD_compensate);
dreschpe 0:fedcef5319f5 106 this->frame_sram_repeat(old_image, EPD_white);
dreschpe 0:fedcef5319f5 107 this->frame_sram_repeat(new_image, EPD_inverse);
dreschpe 0:fedcef5319f5 108 this->frame_sram_repeat(new_image, EPD_normal);
dreschpe 0:fedcef5319f5 109 }
dreschpe 0:fedcef5319f5 110 #endif
dreschpe 0:fedcef5319f5 111
dreschpe 0:fedcef5319f5 112 // Low level API calls
dreschpe 0:fedcef5319f5 113 // ===================
dreschpe 0:fedcef5319f5 114
dreschpe 0:fedcef5319f5 115 // single frame refresh
dreschpe 0:fedcef5319f5 116 void frame_fixed(uint8_t fixed_value, EPD_stage stage);
dreschpe 0:fedcef5319f5 117 void frame_data(const uint8_t *new_image, EPD_stage stage);
dreschpe 0:fedcef5319f5 118 #if defined(EPD_ENABLE_EXTRA_SRAM)
dreschpe 0:fedcef5319f5 119 void frame_sram(const uint8_t *new_image, EPD_stage stage);
dreschpe 0:fedcef5319f5 120 #endif
dreschpe 0:fedcef5319f5 121 void frame_cb(uint32_t address, EPD_reader *reader, EPD_stage stage);
dreschpe 0:fedcef5319f5 122
dreschpe 0:fedcef5319f5 123 // stage_time frame refresh
dreschpe 0:fedcef5319f5 124 void frame_fixed_repeat(uint8_t fixed_value, EPD_stage stage);
dreschpe 0:fedcef5319f5 125 void frame_data_repeat(const uint8_t *new_image, EPD_stage stage);
dreschpe 0:fedcef5319f5 126 #if defined(EPD_ENABLE_EXTRA_SRAM)
dreschpe 0:fedcef5319f5 127 void frame_sram_repeat(const uint8_t *new_image, EPD_stage stage);
dreschpe 0:fedcef5319f5 128 #endif
dreschpe 0:fedcef5319f5 129 void frame_cb_repeat(uint32_t address, EPD_reader *reader, EPD_stage stage);
dreschpe 0:fedcef5319f5 130
dreschpe 0:fedcef5319f5 131 // convert temperature to compensation factor
dreschpe 0:fedcef5319f5 132 int temperature_to_factor_10x(int temperature);
dreschpe 0:fedcef5319f5 133
dreschpe 0:fedcef5319f5 134 // single line display - very low-level
dreschpe 0:fedcef5319f5 135 // also has to handle AVR progmem
dreschpe 0:fedcef5319f5 136 void line(uint16_t line, const uint8_t *data, uint8_t fixed_value, bool read_progmem, EPD_stage stage);
dreschpe 0:fedcef5319f5 137
dreschpe 0:fedcef5319f5 138 // inline static void attachInterrupt();
dreschpe 0:fedcef5319f5 139 // inline static void detachInterrupt();
dreschpe 0:fedcef5319f5 140
dreschpe 0:fedcef5319f5 141 EPD_Class(EPD_size size,
dreschpe 0:fedcef5319f5 142 PinName panel_on_pin,
dreschpe 0:fedcef5319f5 143 PinName border_pin,
dreschpe 0:fedcef5319f5 144 PinName discharge_pin,
dreschpe 0:fedcef5319f5 145 PinName pwm_pin,
dreschpe 0:fedcef5319f5 146 PinName reset_pin,
dreschpe 0:fedcef5319f5 147 PinName busy_pin,
dreschpe 0:fedcef5319f5 148 PinName chip_select_pin,
dreschpe 0:fedcef5319f5 149 PinName mosi,
dreschpe 0:fedcef5319f5 150 PinName miso,
dreschpe 0:fedcef5319f5 151 PinName sck);
dreschpe 0:fedcef5319f5 152
dreschpe 0:fedcef5319f5 153 };
dreschpe 0:fedcef5319f5 154
dreschpe 0:fedcef5319f5 155 #endif
dreschpe 0:fedcef5319f5 156