Member
Posts: 16
Karma: 25544
Join Date: Feb 2012
Device: Kindle 3
|
Here's a little demo using the code from the first post. I'm not sure if it's the right place for it, but the demo is too small to deserve it's own thread.
You really must see this running, the screens don't do justice.
Spoiler:
Code:
//====================================================
// colorOverflow 1.0 - a kindle demo
// Copyright (C) 2012 by geekmaster, with MIT license:
// Copyright (C) 2012 by kiri, with MIT license:
// http://www.opensource.org/licenses/mit-license.php
//----------------------------------------------------
// This was tested on K3.
//----------------------------------------------------
#include <stdio.h> // printf
#include <stdlib.h> // malloc, free, atoi
#include <string.h> // memset, memcpy
#include <unistd.h> // usleep
#include <fcntl.h> // open, close, write
#include <time.h> // time
#include <math.h> // sin, cos
#include <sys/ioctl.h> // ioctl
#include <sys/time.h> // gettime
#include <sys/mman.h> // mmap, munmap
typedef unsigned char u8;
unsigned int __invalid_size_argument_for_IOC;
#include <linux/fb.h> // screeninfo
#include <linux/einkfb.h>
#include <linux/mxcfb.h>
#define WIDTH 600
#define HEIGHT 800
#define NUM 8
#define RAD 111
typedef struct {
float posx, posy, velx, vely;
} blob;
enum GMLIB_op { GMLIB_INIT,GMLIB_CLOSE,GMLIB_UPDATE };
// function prototypes
int gmlib(int);
inline void setpx(int,int,int);
inline int getpx(int,int);
void dblit(void);
int getmsec(void);
void updateBlob(blob *);
// gmlib global vars
static __u8 dt[64]= {
3,129,34,160,10,136,42,168,192,66,223,97,200,73,231,105,50,
176,18,144,58,184,26,152,239,113,207,81,247,121,215,89,14,
140,46,180,7,133,38,164,203,77,235,109,196,70,227,101,62,188,
30,156,54,180,22,148,251,125,219,93,243,117,211,85
}; // 0-255 dither table
__u8 *psave=NULL; // screensave pointer
__u8 *fb0=NULL; // framebuffer pointer
__u8 *wb0=NULL; // workbuffer pointer
__u32 mpu=100; // msec/update
int fdFB=0; // fb0 file descriptor
int fdWB=0; // wb0 file descriptor
__u32 fs=0; // fb0 stride
__u32 fb=0; // fb0 bytes
__u32 MX=0; // xres (visible)
__u32 MY=0; // yres (visible)
__u8 ppb=0; // pixels per byte
int bs=340; // border size
__u8 gs=0; // 8-bit grayscale
__u32 teu=0; // eink update time
__u32 tpu=0; // physics update time
void colorOverflow(void) {
//system("eips -c"); //clear screen
srand ( time(NULL) );
int i, j, n, x, y;
blob blobs[NUM];
for (i=0; i<NUM; i++) {
//populate the array
blob b = {rand()%WIDTH, rand()%HEIGHT, 10+rand()%10, 10+rand()%10};
blobs[i] = b;
}
printf("blobs populated\n");
//clear
for (i=0;i<WIDTH;i++)
for (j=0;j<HEIGHT;j++)
setpx(i,j,0);
int radsq = RAD*RAD, dx, dy, dist;
for (;;) {
for (n=0; n<NUM; n++) {
//draw the blobs
updateBlob(&blobs[n]);
x = blobs[n].posx;
y = blobs[n].posy;
for (j = y-RAD; j <= y; j++) {
for (i = x-RAD; i <= x; i++) {
dx=x-i;
dy=y-j;
dist = (dx*dx+dy*dy);
if (dist<=radsq) {
float q = (float)dist/radsq;
int c = 10*q;
setpx(i,j,c+getpx(i,j));
setpx(2*x-i,j,c+getpx(2*x-i,j));
setpx(i,2*y-j,c+getpx(i,2*y-j));
setpx(2*x-i,2*y-j,c+getpx(2*x-i,2*y-j));
}
}
}
}
gmlib(GMLIB_UPDATE);
}
}
void updateBlob(blob *b) {
if (b->posx + b->velx >= WIDTH || b->posx + b->velx < 0)
b->velx *= -1;
if (b->posy + b->vely >= HEIGHT || b->posy + b->vely < 0)
b->vely *= -1;
b->posx += b->velx;
b->posy += b->vely;
}
//====================================
// gmlib - geekmaster function library
// op (init, update, close)
//------------------------------------
int gmlib(int op) {
static struct update_area_t ua= {0,0,600,800,fx_invert,NULL};
static struct mxcfb_update_data ur= {
{0,0,600,800},WAVEFORM_MODE_AUTO,0,1,TEMP_USE_AMBIENT,0
};
static int eupcode;
static void *eupdata=NULL;
struct fb_var_screeninfo screeninfo;
if (GMLIB_INIT==op) {
teu=getmsec();
// save original screen
fdFB=open("/dev/fb0",O_RDWR); // open eink framebuffer fb0
ioctl(fdFB,FBIOGET_VSCREENINFO,&screeninfo);
ppb=8/screeninfo.bits_per_pixel; // pixels per byte
fs=screeninfo.xres_virtual/ppb; // fb0 stride
fb=screeninfo.yres_virtual/ppb; // fb0 bytes
MX=screeninfo.xres; // max X+1
MY=screeninfo.yres; // max Y+1
ua.x2=MX;
ua.y2=MY;
ur.update_region.width=MX;
ur.update_region.height=MY;
fdWB=open("/tmp/wb0",O_RDWR|O_CREAT); // open work framebuffer wb0
lseek(fdWB,MY*MX-1,SEEK_SET);
write(fdWB,"",1); // create work buffer file
fb0=(__u8 *)mmap(0,MY*fs,PROT_READ|PROT_WRITE,MAP_SHARED,fdFB,0); // map fb0
wb0=(__u8 *)mmap(0,MY*MX,PROT_READ|PROT_WRITE,MAP_SHARED,fdWB,0); // map wb0
if (fb>MY) {
eupcode=MXCFB_SEND_UPDATE;
eupdata=&ur;
ur.update_mode=0;
} else {
eupcode=FBIO_EINK_UPDATE_DISPLAY_AREA;
eupdata=&ua;
}
psave=malloc(fs*MY);
memcpy(psave,fb0,fs*MY);
memset(wb0,0,MY*MX);
gmlib(GMLIB_UPDATE);
teu+=300;
memset(wb0,255,MY*MX);
gmlib(GMLIB_UPDATE);
teu+=80;
} else if (GMLIB_UPDATE==op) {
while (teu>getmsec()); // async update needs time
dblit();
ioctl(fdFB,eupcode,eupdata);
} else if (GMLIB_CLOSE==op) {
gmlib(GMLIB_UPDATE); //sleep(3); does it really need to sleep?
memcpy(fb0,psave,fs*MY); // restore display
free(psave);
gmlib(GMLIB_UPDATE); // update display
munmap(wb0,MY*MX); // unmap wb0
close(fdWB); // close wb0
remove("/tmp/wb0"); // remove wb0
munmap(fb0,MY*fs); // unmap fb0
close(fdFB); // close fb0
} else {
return -1;
}
return 0;
}
//========================================
// setpx - draw pixel to 8-bit work buffer
// x,y:screen coordinates, c:color(0-255).
//----------------------------------------
inline void setpx(int x,int y,int c) {
if (x>=WIDTH || x<0 || y>=HEIGHT || y<0)
return;
wb0[y*MX+x]=c;
}
//========================================
// getpx - returns the value of a pixel
// from the 8-bit work buffer
// x,y:screen coordinates, returns:color(0-255).
//----------------------------------------
inline int getpx(int x,int y) {
//all offscreen pixels are returned as white
if (x>=WIDTH || x<0 || y>=HEIGHT || y<0) return 255;
return wb0[y*MX+x];
}
//==========================
// dblit - dither wb0 to fb0
//--------------------------
void dblit(void) {
int x,y,ys;
__u8 p,d,*pi,*po,*pd;
pi=wb0-1;
po=fb0-1;
if (gs) { // 16-color dither
if (ppb/2) { // 2 px/byte
for (y=0; y<MY; y++) {
pd=dt+(y&7)*8+7;
for (x=0; x<MX; x+=8) {
pd-=8;
p=*pi++;
d=*pd++;
*po++=((p&240)+(d-(*pi&15)*255/15>>4&16)-16)&240|
((*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16)/16&15;
p=*pi++;
d=*pd++;
*po++=((p&240)+(d-(*pi&15)*255/15>>4&16)-16)&240|
((*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16)/16&15;
p=*pi++;
d=*pd++;
*po++=((p&240)+(d-(*pi&15)*255/15>>4&16)-16)&240|
((*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16)/16&15;
p=*pi++;
d=*pd++;
*po++=((p&240)+(d-(*pi&15)*255/15>>4&16)-16)&240|
((*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16)/16&15;
}
}
} else { // 1 px/byte
for (y=0; y<MY; y++) {
pd=dt+(y&7)*8+7;
for (x=0; x<MX; x+=8) {
pd-=8;
// *po++=(*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16;
*po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
*po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
*po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
*po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
*po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
*po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
*po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
*po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
}
po+=(fs-MX);
}
}
} else { // 2-color dither
if (ppb/2) { // 2 px/byte *** broken (high contrast) ***
for (y=0; y<MY; y++) {
pd=dt+(y&7)*8+7;
ys=(y&7)*8;
for (x=0; x<MX; x+=8) {
pd-=8;
p=*pi++;
d=*pd++;
*po++=d-p>>4&240|*pd++-*pi++>>8&15;
p=*pi++;
d=*pd++;
*po++=d-p>>4&240|*pd++-*pi++>>8&15;
p=*pi++;
d=*pd++;
*po++=d-p>>4&240|*pd++-*pi++>>8&15;
p=*pi++;
d=*pd++;
*po++=d-p>>4&240|*pd++-*pi++>>8&15;
}
}
} else { // 1 px/byte
for (y=0; y<MY; y++) {
pd=dt+(y&7)*8+7;
for (x=0; x<MX; x+=8) {
pd-=8;
*po++=*pd++-*pi++>>8;
*po++=*pd++-*pi++>>8;
*po++=*pd++-*pi++>>8;
*po++=*pd++-*pi++>>8;
*po++=*pd++-*pi++>>8;
*po++=*pd++-*pi++>>8;
*po++=*pd++-*pi++>>8;
*po++=*pd++-*pi++>>8;
}
po+=(fs-MX);
}
}
}
}
//====================================
// getmsec - get msec since first call
// (tick counter wraps every 12 days)
//------------------------------------
int getmsec(void) {
int tc;
static int ts=0;
struct timeval tv;
gettimeofday(&tv,NULL);
tc=tv.tv_usec/1000+1000*(0xFFFFF&tv.tv_sec);
if (0==tc) {
ts=tc;
}
return tc-ts;
}
//==================
// main - start here
//------------------
int main(void) {
gmlib(GMLIB_INIT);
gs=0; // 0 for binary dither, 1 for grayscale dither
colorOverflow();
gmlib(GMLIB_CLOSE);
return 0;
}
Last edited by kiri87; 05-10-2012 at 02:45 AM.
|