Skip to content

Commit

Permalink
Merge pull request #74 from tvoverbeek/PUstagetime
Browse files Browse the repository at this point in the history
Implement Fast Update by setting stage time directly

@CharmingSu @repaper pulling in this PR as haven't heard from you. If you have any objection please let us know
  • Loading branch information
shawaj authored Aug 14, 2017
2 parents 81e4590 + daa959e commit 2a72cff
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 6 deletions.
3 changes: 3 additions & 0 deletions PlatformWithOS/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ panel Read Only String describing the panel and giving its pixel width
current Read Only Binary image that matches the currently displayed image (big endian)
display Read Write Image being assembled for next display (big endian)
temperature Read Write Set this to the current temperature in Celsius
f_stage_time Read Write Set stage time in milliseconds for 'F' command
command Write Only Execute display operation
BE Directory Big endian version of current and display
LE Directory Little endian version of current and display
Expand All @@ -112,6 +113,8 @@ Command Byte Description
-------- ----- --------------------------------
'C' 0x43 Clear the EPD, set `current` to all zeros, `display` is not affected
'U' 0x5A Erase `current` from EPD, output `display` to EPD, copy display to `current`
'P' 0x50 Do partial update of display by only updating the changed parts
'F' 0x46 Same as partial update, but use user defined stage time

Notes:

Expand Down
4 changes: 4 additions & 0 deletions PlatformWithOS/driver-common/V110_G1/epd.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,10 @@ void EPD_set_temperature(EPD_type *epd, int temperature) {
epd->factored_stage_time = epd->stage_time * temperature_to_factor_10x(temperature) / 10;
}

void EPD_set_factored_stage_time(EPD_type *epd, int pu_stagetime) {
epd->factored_stage_time = pu_stagetime;
}

// clear display (anything -> white)
void EPD_clear(EPD_type *epd) {
frame_fixed_repeat(epd, 0xff, EPD_compensate);
Expand Down
3 changes: 3 additions & 0 deletions PlatformWithOS/driver-common/V110_G1/epd.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ void EPD_destroy(EPD_type *epd);
// set the temperature compensation (call before begin)
void EPD_set_temperature(EPD_type *epd, int temperature);

// set factored_stage_time directly ('F' command)
void EPD_set_factored_stage_time(EPD_type *epd, int pu_stagetime);

// sequence start/end
void EPD_begin(EPD_type *epd);
void EPD_end(EPD_type *epd);
Expand Down
4 changes: 4 additions & 0 deletions PlatformWithOS/driver-common/V231_G2/epd.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,10 @@ void EPD_set_temperature(EPD_type *epd, int temperature) {
epd->factored_stage_time = epd->base_stage_time * temperature_to_factor_10x(temperature) / 10;
}

void EPD_set_factored_stage_time(EPD_type *epd, int pu_stagetime) {
epd->factored_stage_time = pu_stagetime;
}


// clear display (anything -> white)
void EPD_clear(EPD_type *epd) {
Expand Down
3 changes: 3 additions & 0 deletions PlatformWithOS/driver-common/V231_G2/epd.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ void EPD_destroy(EPD_type *epd);
// set the temperature compensation (call before begin)
void EPD_set_temperature(EPD_type *epd, int temperature);

// set factored_stage_time directly ('F' command)
void EPD_set_factored_stage_time(EPD_type *epd, int pu_stagetime);

// sequence start/end
void EPD_begin(EPD_type *epd);
void EPD_end(EPD_type *epd);
Expand Down
47 changes: 43 additions & 4 deletions PlatformWithOS/driver-common/epd_fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,16 @@ static const char *display_path = "/display"; // the next imag
static const char *display_inverted_path = "/display_inverse"; // the next image to display
static const char *command_path = "/command"; // any write transfers display -> EPD and updates current
static const char *temperature_path = "/temperature"; // read/write temperature compensation setting
static const char *pu_stagetime_path = "/pu_stagetime"; // stagetime to use for 'F' command,
// bypassing temperature compensation.
static const char *error_path = "/error"; // error text
static const char *spi_device = SPI_DEVICE; // default SPI device path
static const uint32_t spi_bps = SPI_BPS; // default SPI device speed

// expect that external process changes this just before update command
// by sending text string e.g. shell: echo 19 > /dev/epd/temperature
static int temperature = 25; // for external temperature compensation
static int pu_stagetime = 500; // stagetime to use in 'F' command

#define MAKE_STRING_HELPER(s) #s
#define MAKE_STRING(s) MAKE_STRING_HELPER(s)
Expand Down Expand Up @@ -184,6 +187,11 @@ static int display_getattr(const char *path, struct stat *stbuf) {
stbuf->st_nlink = 1;
stbuf->st_size = 4;

} else if (strcmp(path, pu_stagetime_path) == 0) {
stbuf->st_mode = S_IFREG | 0666;
stbuf->st_nlink = 1;
stbuf->st_size = 5;

} else if (strcmp(path, error_path) == 0) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
Expand Down Expand Up @@ -212,6 +220,7 @@ static int display_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
filler(buf, panel_path + 1, NULL, 0);
filler(buf, command_path + 1, NULL, 0);
filler(buf, temperature_path + 1, NULL, 0);
filler(buf, pu_stagetime_path + 1, NULL, 0);
filler(buf, version_path + 1, NULL, 0);
filler(buf, error_path + 1, NULL, 0);
return 0;
Expand All @@ -233,7 +242,8 @@ static int display_open(const char *path, struct fuse_file_info *fi) {

// read-write items
if (strcmp(path, command_path) == 0 ||
strcmp(path, temperature_path) == 0) {
strcmp(path, temperature_path) == 0 ||
strcmp(path, pu_stagetime_path) == 0) {
write_allowed = true;
} else if (strcmp(path, panel_path) == 0 ||
strcmp(path, version_path) == 0 ||
Expand Down Expand Up @@ -286,7 +296,8 @@ static int display_create(const char *path, mode_t mode, struct fuse_file_info *
(void) fi;

if (strcmp(path, command_path) == 0 ||
strcmp(path, temperature_path) == 0) {
strcmp(path, temperature_path) == 0 ||
strcmp(path, pu_stagetime_path) == 0) {
return 0;
}

Expand All @@ -308,7 +319,8 @@ static int display_create(const char *path, mode_t mode, struct fuse_file_info *
static int display_truncate(const char *path, off_t offset) {
(void) offset;
if (strcmp(path, command_path) == 0 ||
strcmp(path, temperature_path) == 0) {
strcmp(path, temperature_path) == 0 ||
strcmp(path, pu_stagetime_path) == 0) {
return 0;
}

Expand Down Expand Up @@ -362,6 +374,16 @@ static int display_read(const char *path, char *buffer, size_t size, off_t offse
char t_buffer[16];
int length = snprintf(t_buffer, sizeof(t_buffer), "%3d\n", t);
return buffer_read(buffer, size, offset, t_buffer, length, false, false);
} else if (strcmp(path, pu_stagetime_path) == 0) {
int s = pu_stagetime;
if (s < 50) {
s = 50;
} else if (s > 2000) {
s = 2000;
}
char s_buffer[16];
int length = snprintf(s_buffer, sizeof(s_buffer), "%4d\n", s);
return buffer_read(buffer, size, offset, s_buffer, length, false, false);
} else if (strcmp(path, error_path) == 0) {
const char *t_buf = error_texts[EPD_status(epd)];
return buffer_read(buffer, size, offset, t_buf, strlen(t_buf), false, false);
Expand Down Expand Up @@ -411,6 +433,15 @@ static int display_write(const char *path, const char *buffer, size_t size, off_
}
}
return size;
} else if (strcmp(path, pu_stagetime_path) == 0) {
if (size > 0) {
char *end = NULL;
long int s = strtol(buffer, &end, 0);
if (buffer != end && s >= 50 && s <= 2000) {
pu_stagetime = (int)s;
}
}
return size;
}

// test big/little endian
Expand Down Expand Up @@ -607,7 +638,15 @@ static void run_command(const char c) {
break;

case 'P': // partial update with contents of display
EPD_set_temperature(epd, temperature);
case 'F': // partial update bypassing temperature compensation for stagetime
if (c == 'P') {
EPD_set_temperature(epd, temperature);
}
#if EPD_PARTIAL_AVAILABLE
else {
EPD_set_factored_stage_time(epd, pu_stagetime);
}
#endif
EPD_begin(epd);
if (EPD_OK != EPD_status(epd)) {
warn("EPD_begin failed");
Expand Down
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
# gratis
## Partial Update implementation notes, February 2016
## Fast Update notes, July 2017

This branch implements a proper partial update following the algorithm outlined
The update rate for Partial Update is determined by the temperature dependent stage time.
For 25 degrees C a typical max update rate for the 2.7" display is about 1.5 Hz.

The stage time decreases as the measured temperature increases.
For some applications a faster update rate can be useful.
This can be achieved by setting the stage time directly bypassing the normal temperature
dependent setting of the stage time.
This is the same mechanism as used in the Pervasive Displays Windows application for the
TI Launchpad and the EXT2 development board (http://www.pervasivedisplays.com/kits/ext2_kit).

Decreasing the stage time increases the max update rate. If the stage time gets too small
some ghosting (left overs from the previous image) will occur.
Depending on the application some ghosting may be acceptable.

This implementation uses the 'F' command to do a Fast Update using the stage time as set in
/dev/epd/f_stage_time.

A video demonstrating the normal Partial Update and Fast Update for various stage times is
available on YouTube.
[![Fast Update Demo](https://img.youtube.com/vi/neGKnfJFHx4/0.jpg)](https://www.youtube.com/watch?v=neGKnfJFHx4)

## Partial Update notes, February 2016

This partial update implementation follows the algorithm outlined
in the discussion of issue #19 on the repaper/gratis github repository.

The original code in epd_fuse.c and V231G2/epd.c under PlatformWithOS did a full 4 cycle display update
Expand Down

0 comments on commit 2a72cff

Please sign in to comment.