Display Information

Accessing the Display

The display is accessed through /dev/display. You can mmap() 2048 bytes from this device and read from or write to it.

The display is 128x32, 2bpp. The memory layout is fairly straight-forward: 32 rows of 64 bytes each, where rows are laid left-to-right, top-to-bottom, and each byte contains two 4-bit pixel values. The architecture is little-endian, so bits 0-3 correspond to the "left" pixel, and bits 4-7 are the "right" pixel. Since the display only supports 2bpp, only pixel values 0-3 are meaningful; the two highest bits are currently ignored. Value 0 is off; 1 is dim; 2 is medium; 3 is full brightness.

Changes you make to the display will not become active until you call ioctl(fd, _IO('d', 0)).

It is further possible to buffer and synchronize screen updates with the audio DMA, but documentation of this feature is not yet available.

The entire display can be turned on and off with ioctl(fd, _IOW('d', 1, int), state) where state is 1 (on) or 0 (off). When the display is off, the front LED is enabled.

The LED can also be controlled, but no specification is available at this time.

Contributed by Rob Leslie

Example

Here is a sample program which reads 2048 bytes from standard input, dumps them onto the display, and turns it on (in case it was off):

dblit.c

# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>

# include <unistd.h>
# include <sys/mman.h>

# include <sys/ioctl.h>

# define BLIT(fd)        ioctl((fd), _IO('d', 0))
# define DISPLAY(fd, x)  ioctl((fd), _IOW('d', 1, int), (x))

int main(int argc, char *argv[])
{
  int fd;
  caddr_t dmap;

  fd = open("/dev/display", O_RDWR);
  if (fd == -1)
    return 1;

  dmap = mmap(0, 2048, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (dmap == (caddr_t) -1)
    return 2;

  if (read(STDIN_FILENO, dmap, 2048) == -1)
    return -1;

  BLIT(fd);
  DISPLAY(fd, 1);

  if (munmap(dmap, 2048) == -1 ||
      close(fd) == -1)
    return 3;

  return 0;
}

If you don't have a suitable bitmap image handy to test, try feeding in /dev/urandom or /dev/zero. A similar program can be written to copy the display to standard output.

Contributed by Rob Leslie

Image Conversion

The above sample program just blits from stdin to display in the display's raw format, which is 4-bits per pixel (little-endian).

I took the same code and added 8-bit -> 4-bit conversion to it, so that you can load raw files with the example below. But if you consider programming anything in larger scale, I would suggest to write a proper image reader.

So, to get your image to the display:

  1. compile the program below
  2. make your image 128x32 sized (image can use all 256 grayscales)
  3. after your image is ready, go to Image/Mode/Grayscale in Photoshop
  4. go to File/Save As, choose the .RAW format
  5. use the default options, header being 0 sized
  6. transfer the image to empeg (file size should be 4096 bytes)
  7. run blitraw < pic.raw on your empeg, if you named the program as blitraw and image as pic.raw

This is the easiest way to get your own image to the empeg's display but also the most unsophisticated way to do it. It relies that the raw image file has no palette and that 0 means black and 255 white, on color indices. And it only works with 128x32 images.

blitraw.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#define BLIT(fd)	ioctl((fd), _IO('d', 0))
#define DISPLAY(fd, x)	ioctl((fd), _IOW('d', 1, int), (x))

int main(int argc, char *argv[])
{
	int fd;
	caddr_t dmap;
	int i = 0, j = 0;
	char cBuffer[ 4096 ];
	char cLeft = 0, cRight = 0;

	fd = open("/dev/display", O_RDWR);
	if(fd == -1)
		return 1;

	dmap = mmap(0, 2048, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (dmap == (caddr_t) -1)
		return 2;

	if( read( STDIN_FILENO, cBuffer, 4096 ) == -1 )
		return -1;

	// shuffle bits
	for( i = 0; i < 4096; i+=2, ++j )
	{
		cLeft = cBuffer[ i ] >> 6;
		cRight = cBuffer[ i+1 ] >> 6;
		dmap[ j ] = (cRight << 4) | cLeft;
	}

	BLIT(fd);
	DISPLAY(fd, 1);

	if (munmap(dmap, 2048) == -1 || close(fd) == -1)
		return 3;

	return 0;
}
Contributed by Kim Salo